我有一个数据框(14.5K行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
我的猜测是,有一些新病人的名字不在之前的数据框中,因此不知道给予那些人的等级。同样在“推荐医生”专栏中有新的看不见的名字。
解决方案是什么?
答案 0 :(得分:30)
这可能是由于两个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
代替真值
我想:
解决方案:
找到错误的列并找出其错误和修复的原因。消除原因不是症状。
答案 1 :(得分:27)
“简单”的方法是在导入文本数据时不将字符串设置为因子。
请注意,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)
答案 2 :(得分:9)
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
答案 3 :(得分:4)
根据上一个答案的建议,将列作为字符读取,并在rbind
之后转换为因子。
SQLFetch
(我假设 RODBC )还有stringsAsFactors
或as.is
参数来控制字符的转换。
允许的值与read.table
相同,例如as.is=TRUE
或某些列号。
答案 4 :(得分:3)
我遇到了类型不匹配的问题,尤其是因素。我不得不将两个兼容的数据集粘合在一起。
我的解决方案是将两个数据帧中的因子转换为“字符”。然后它就像一个魅力: - )
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)
}
如果要查看两个数据框中的类型,请运行(更改var名称):
cbind("orig"=sapply(allSurveyData, class),
"merge" = sapply(curSurveyDataMerge, class),
"eq"=sapply(allSurveyData, class) == sapply(curSurveyDataMerge, class)
)
答案 5 :(得分:2)
创建数据框时,您可以选择将字符串列设为因子(*.data.example.com
),或将它们保留为字符串。
对于您的情况,请不要使用字符串列因子。将它们保持为字符串,然后附加工作正常。如果您需要它们最终成为因子,请执行所有插入并首先作为字符串追加,然后最终将它们转换为因子。
如果你创建了字符串列因子,然后附加包含看不见的值的行,你会得到你在每个新的看不见的因子级别上提到的错误,并且该值被NA替换...
stringsAsFactors=T
所以不要使你的字符串列因子。将它们保留为字符串,然后附加正常工作:
> 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)
答案 6 :(得分:0)
这是一个函数,用于获取2个数据帧的公共行名称并执行rbind,其中我们基本上找到作为因子的字段,添加新因子然后执行rbind。这应该解决任何因素问题:
rbindCommonCols&lt; -function(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
}