Уровни невидимого фактора при добавлении новых записей с невидимыми строковыми значениями во фрейм данных вызывают предупреждение и приводят к NA

StackOverflow https://stackoverflow.com/questions/1632772

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня есть фрейм данных (14,5 тыс. строк по 15 столбцам), содержащий платежные данные за период с 2001 по 2007 год.

Я добавляю к нему новые данные за 2008 год с помощью: alltime <- rbind(alltime,all2008)

К сожалению, это приводит к появлению предупреждения:

> Warning message:
In `[<-.factor`(`*tmp*`, ri, value = c(NA, NA, NA, NA, NA, NA, NA,  :
  invalid factor level, NAs generated

Я предполагаю, что есть несколько новых пациентов, имен которых не было в предыдущем фрейме данных, и поэтому он не знал бы, какой уровень им присвоить.Аналогично, появились новые невидимые имена в столбце "направляющий врач".

Каково же решение?

Это было полезно?

Решение

Это может быть вызвано несоответствием типов в двух data.frames.

Прежде всего проверьте типы (классы).В диагностических целях сделайте это:

new2old <- rbind( alltime, all2008 ) # this gives you a warning
old2new <- rbind( all2008, alltime ) # this should be without warning

cbind(
    alltime = sapply( alltime, class),
    all2008 = sapply( all2008, class),
    new2old = sapply( new2old, class),
    old2new = sapply( old2new, class)
)

Я ожидаю, что там будет скандал, похожий на:

            alltime  all2008   new2old  old2new
...         ...      ...       ...      ...
some_column "factor" "numeric" "factor" "character"
...         ...      ...       ...      ...

Если это так, то объяснение:rbind не проверяйте соответствие типов.Если вы проанализируете rbind.data.frame затем вы могли видеть, что первый аргумент инициализирует выходные типы.Если в первом типе data.frame является фактором, то столбец output data.frame является фактором с уровнями unique(c(levels(x1),levels(x2))).Но когда во втором столбце data.frame это не фактор, тогда levels(x2) является NULL, таким образом, уровни не расширяются.

Это означает, что ваши выходные данные неверны!Есть такие NA's вместо истинных значений

Я полагаю , что:

  1. вы создаете свои старые данные с другой версией R / RODBC, поэтому типы были созданы разными методами (возможно, с разными настройками - десятичный разделитель)
  2. в проблемном столбце есть NULL или какие-то конкретные данные, например.кто-нибудь, измените столбец в базе данных.

Решение:

найдите неправильный столбец и найдите причину, почему он неправильный, и исправьте его.Устраните причину, а не симптомы.

Другие советы

" easy " Можно просто не указывать строки в качестве факторов при импорте текстовых данных.

Обратите внимание, что функции read.{table,csv,...} принимают параметр stringsAsFactors, который по умолчанию установлен на TRUE. Вы можете установить его на FALSE во время импорта и rbind - данных.

Если вы хотите, чтобы столбец был фактором в конце, вы можете сделать это тоже.

Например:

alltime <- read.table("alltime.txt", stringsAsFactors=FALSE)
all2008 <- read.table("all2008.txt", stringsAsFactors=FALSE)
alltime <- rbind(alltime, all2008)
# If you want the doctor column to be a factor, make it so:
alltime$doctor <- as.factor(alltime$doctor)

1) создайте фрейм данных с параметром stringsAsFactor, имеющим значение FALSE.Это должно решить проблему с фактором

2) после этого не используйте rbind - это портит имена столбцов, если фрейм данных пуст.просто сделайте это таким образом:

df[nrow(df)+1,] <- c("d","gsgsgd",4)

/

> df <- data.frame(a = character(0), b=character(0), c=numeric(0))

> df[nrow(df)+1,] <- c("d","gsgsgd",4)

Warnmeldungen:
1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
  invalid factor level, NAs generated
2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
  invalid factor level, NAs generated

> df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)

> df[nrow(df)+1,] <- c("d","gsgsgd",4)

> df
  a      b c
1 d gsgsgd 4

Как было предложено в предыдущем ответе, прочитайте столбцы как символы и выполните преобразование в коэффициенты после rbind. SQLFetch (я полагаю, RODBC ) также имеет аргумент stringsAsFactors или as.is для управления преобразованием символов. Допустимые значения: read.table, например, as.is=TRUE или номер столбца.

У меня была такая же проблема с несоответствиями типов, особенно с факторами. Мне пришлось склеить два набора данных, которые в противном случае были бы совместимы.

Мое решение состоит в том, чтобы преобразовать факторы в обоих информационных кадрах в " символ " ;. Тогда это работает как шарм: -)

    convert.factors.to.strings.in.dataframe <- function(dataframe)
    {
        class.data  <- sapply(dataframe, class)
        factor.vars <- class.data[class.data == "factor"]
        for (colname in names(factor.vars))
        {
            dataframe[,colname] <- as.character(dataframe[,colname])
        }
        return (dataframe)
    }

Если вы хотите, чтобы типы в ваших двух фреймах данных запускались (измените имена переменных):

    cbind("orig"=sapply(allSurveyData, class), 
          "merge" = sapply(curSurveyDataMerge, class),
          "eq"=sapply(allSurveyData, class) == sapply(curSurveyDataMerge, class)
    )

Когда вы создаете фрейм данных, у вас есть выбор: использовать факторы столбцов строк (stringsAsFactors=T) или оставить их в виде строк.

Для вашего случая не делайте ваши столбцы строк факторами. Сохраняйте их как строки, тогда добавление отлично работает. Если вы хотите, чтобы они в конечном итоге были факторами, сначала вставьте и добавьте их как строку, а затем, наконец, преобразуйте их в фактор.

Если вы сделаете строковые столбцы факторами, а затем добавите строки, содержащие невидимые значения, вы получите ошибку, которую вы упомянули на каждом новом невидимом уровне факторов, и это значение будет заменено на NA ...

> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=T)

  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X

> df <- rbind(df, c('Denise','Z'))
Warning messages:
1: In `[<-.factor`(`*tmp*`, ri, value = "Denise") :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, ri, value = "Z") :
  invalid factor level, NA generated
> df
  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X
4    <NA>             <NA>

Так что не делайте ваши столбцы строк факторами. Сохраняйте их как строки, тогда добавление отлично работает :

> df <- data.frame(patient=c('Ann','Bob','Carol'), referring_doctor=c('X','Y','X'), stringsAsFactors=F)
> df <- rbind(df, c('Denise','Z'))
  patient referring_doctor
1     Ann                X
2     Bob                Y
3   Carol                X
4  Denise                Z

Чтобы изменить поведение по умолчанию :

options(stringsAsFactors=F)

Чтобы преобразовать отдельные столбцы в / из строки или фактора

df$col <- as.character(df$col)
df$col <- as.factor(df$col)

вот функция, которая берет общие имена строк из 2 фреймов данных и выполняет rbind, где мы в основном находим поля, являющиеся факторами, добавляем новые факторы, затем выполняем rbind.Это должно позаботиться о любых факторных проблемах:

Rbindcommon - файлы<-функция(x, y){

commonColNames = intersect(colnames(x), colnames(y))
x = x[,commonColNames]
y = y[,commonColNames]

colClassesX = sapply(x, class)
colClassesY = sapply(y, class)
classMatch = paste( colClassesX, colClassesY, sep = "-" )
factorColIdx = grep("factor", classMatch)

for(n in factorColIdx){ 
    x[,n] = as.factor(x[,n])
    y[,n] = as.factor(y[,n])
}

for(n in factorColIdx){ 
    x[,n] = factor(x[,n], levels = unique(c( levels(x[,n]), levels(y[,n]) )))
    y[,n] = factor(y[,n], levels = unique(c( levels(y[,n]), levels(x[,n]) )))  
} 

res = rbind(x,y)
res

}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top