9

rbind当使用两个data.framesNA值时,我对 R 强制变量类型的方式有疑问。我举例说明:

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同时保留变量类型factornumericxy。当我给:

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被强制到角色级别。我很困惑 - 即使我使用其他绑定顺序,它不能保持因子类型吗?对我的代码进行哪些直接更改以实现我的目标?

4

5 回答 5

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 ...
于 2014-02-28T16:40:20.570 回答
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" 
于 2014-02-28T16:51:13.887 回答
3

同样,您可以将列转换NAsfactor

NAs$x<-factor(NAs$x)
dat_backward<-rbind(NAs,dat) 
is.factor(dat_backward$x) # TRUE
is.character(dat_backward$x) # FALSE
于 2014-02-28T16:38:45.117 回答
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 ...
于 2014-02-28T16:35:31.383 回答
0

一种方法是NAs使用正确的列数据类型进行创建。这可以很容易地完成

NAs <- dat[NA,]

您还可以根据需要制作任意数量的行

num.rows <- 30
NAs <- dat[NA,][1:num.rows,]
于 2014-02-28T16:43:31.493 回答