为什么R在将NA值添加到具有因子的数据框时更改变量类型?

时间:2014-02-28 15:59:06

标签: r dataframe na rbind r-factor

在使用rbind两个data.frames NA值时,我对使用变量类型的方式存在问题。我举例说明:

x<-factor(sample(1:3,10,T))
y<-rnorm(10)
dat<-data.frame(x,y)
NAs<-data.frame(matrix(NA,ncol=ncol(dat),nrow=nrow(dat)))
colnames(NAs)<-colnames(dat)

现在的目标是在保留datNAs的变量类型factornumeric的同时附加xy。当我给:

dat_forward<-rbind(dat,NAs)
is.factor(dat_forward$x)

这很好用。但是,使用rbind的向后方向失败:

dat_backward<-rbind(NAs,dat)
is.factor(dat_backward$x)
is.character(dat_backward$x)

现在x被强制为角色等级。我很困惑 - 即使我使用其他绑定顺序,也不能保留因子类型?为实现目标,我的代码会有什么直接的改变?

5 个答案:

答案 0 :(得分:9)

这是一种使列类正确的简单方法:

x <- rbind(dat[1,], NAs, dat)[-1,]
str(x)
#  $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
#  $ y: num  NA NA NA NA NA NA NA NA NA NA ...

更一般地说,如果你真的经常需要这个,你可以创建一个类似rbind的函数,它需要一个额外的参数来指示你的列类的data.frame喜欢强迫所有其他人的专栏:

myrbind <- function(x, ..., template=x) {
    do.call(rbind, c(list(template[1,]), list(x), list(...)))[-1,]
}

str(myrbind(NAs, dat,  template=dat))
# 'data.frame': 20 obs. of  2 variables:
#  $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
#  $ y: num  NA NA NA NA NA NA NA NA NA NA ...

## If no 'template' argument is supplied, myrbind acts just like rbind    
str(myrbind(dat, NAs))
# 'data.frame': 20 obs. of  2 variables:
#  $ x: Factor w/ 3 levels "1","2","3": 3 3 3 3 2 3 1 1 3 2 ...
#  $ y: num  0.303 1.77 -1.38 1.731 0.033 ...

答案 1 :(得分:3)

同样,您只需将NAs中的列转换为factor

即可
NAs$x<-factor(NAs$x)
dat_backward<-rbind(NAs,dat) 
is.factor(dat_backward$x) # TRUE
is.character(dat_backward$x) # FALSE

答案 2 :(得分:3)

data.frame将不同类型放在一起时,

rbind会做很多错误的事情,特别是当涉及因素时。开始使用data.table(1.8.11+),您将不会遇到以下问题:

library(data.table)
dt1 = data.table(dat)
dt2 = data.table(NAs)

sapply(rbind(dt1, dt2), class)
#        x         y 
# "factor" "numeric" 
sapply(rbind(dt2, dt1), class)
#        x         y 
# "factor" "numeric" 

答案 3 :(得分:2)

?rbind.data.frame,我们读到:“然后它从第一个数据框中获取列的类......”。这就是您在致电rbind时看到订单的原因。

要获得dat_forward的变量类dat_backward,您可以构造dat_forward并重新排序行:

dat_new = rbind(dat, NAs)[c((nrow(dat)+1):(nrow(dat)+nrow(NAs)), 1:nrow(dat)),]
str(dat_new)
# 'data.frame': 20 obs. of  2 variables:
#  $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
#  $ y: num  NA NA NA NA NA NA NA NA NA NA ...

答案 4 :(得分:0)

一种方法是使用正确的列数据类型创建NAs。这可以通过

轻松完成
NAs <- dat[NA,]

您也可以根据需要使用

创建尽可能多的行
num.rows <- 30
NAs <- dat[NA,][1:num.rows,]