Добавление строк в dataframe - факторная проблема

У меня есть большой фреймворк (14552 строки по 15 столбцов), содержащий данные биллинга с 2001 по 2007 год. Я использовал sqlFetch для получения данных 2008 года. Чтобы добавить данные за 2008 год к данным за предыдущие 7 лет, можно сделать следующее:

alltime <-rbind(alltime,all2008)

К сожалению, это генерирует

Предупреждающее сообщение: В [<-.factor (*tmp*, ri, value = c (NA, NA, NA, NA, NA, NA, NA,:   недопустимый уровень фактора, генерируемые НС

Моя догадка заключается в том, что есть некоторые новые пациенты, чьи имена не были в предыдущем кадре данных, и поэтому он не знал бы, какой уровень это даст. Другой столбец - для имени референтного врача. Новый врач может вызвать такую ​​же проблему.

Способ R импортирует данные и автоматически выдает то, что является числовым, а что нет (и тем самым делает его фактором) замечательно - пока вам не придется манипулировать им дальше, а затем становится болью. Как я могу преодолеть свою проблему элегантно?

Ответ 1

Это может быть вызвано несоответствием типов в двух 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 есть фактор, то вывод столбца data.frame является фактором с уровнями unique(c(levels(x1),levels(x2))). Но когда во втором столбце data.frame не коэффициент, тогда levels(x2) равен NULL, поэтому уровни не распространяются.

Это означает, что ваши выходные данные неверны! Вместо истинных значений NA

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

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

Решение:

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

Ответ 2

"Легкий" способ состоит в том, чтобы просто не устанавливать ваши строки в качестве факторов при импорте текстовых данных.

Обратите внимание, что функции 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)

Ответ 3

1) создайте фрейм данных со строкамиAsFactor, установленными в 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

Ответ 4

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

Ответ 5

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

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

    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)
    )

Ответ 6

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

rbindCommonCols < -функция (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

}