У меня есть большой фреймворк (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
}