【问题标题】:Why does R change the variable type when prepending NA values to a data frame with factors?为什么在将 NA 值附加到带有因子的数据帧时,R 会更改变量类型?
【发布时间】:2014-04-01 17:37:47
【问题描述】:

当使用两个 data.framesNA 值的 rbind 时,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,同时保留xy 的变量类型factornumeric。当我给:

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

【问题讨论】:

  • 来自?rbind.data.frame:“然后它从第一个数据帧中获取列的类......”。这就是为什么您在致电rbind 时看到订单很重要。
  • @josilber 谢谢,我的问题有直接的解决方法吗?
  • NAs的第一列转换为因子?
  • @josilber rbind(dat[0,], NAs, dat) 似乎与此相矛盾。
  • @MatthewPlourde 文档前面的一句话:“rbind 数据框方法首先丢弃所有零列和零行参数。”

标签: r dataframe na rbind r-factor


【解决方案1】:

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

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

您还可以根据需要创建任意数量的行

num.rows <- 30
NAs <- dat[NA,][1:num.rows,]

【讨论】:

    【解决方案2】:

    这里有一个相当简单的方法来获得正确的列类:

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

    【讨论】:

    • 谢谢,一个简单的解决方案和一个很好的功能。
    【解决方案3】:

    data.framerbind' 将不同类型放在一起时会做很多错误的事情,尤其是在涉及因素时。改用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" 
    

    【讨论】:

      【解决方案4】:

      同样,您可以将NAs 中的列转换为factor

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

      【讨论】:

        【解决方案5】:

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

        要以dat_backward 的顺序获取dat_forward 的变量类,您只需构造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 ...
        

        【讨论】:

          猜你喜欢
          • 2018-11-07
          • 1970-01-01
          • 2019-02-07
          • 2018-02-23
          • 1970-01-01
          • 2016-05-10
          • 2012-01-25
          • 2017-04-12
          • 2021-10-15
          相关资源
          最近更新 更多