【问题标题】:how to programatically assign a bunch of variables within a data frame如何以编程方式在数据框中分配一堆变量
【发布时间】:2014-07-01 10:49:11
【问题描述】:

给定一个字符向量vars 和一个数据帧列表d,我想 确保d 中的每个数据框都包含vars 中命名的所有列。 假设一个数据框中缺少某些列,然后我创建 数据框中的那些列并用NAs 填充它们。

但是,当我使用 assign 执行此操作时,我得到了一些奇怪的结果:

> vars <- c('y','z')
> b <- data.frame(a=1:3, b=3:1)
> b
  a b
1 1 3
2 2 2
3 3 1
> within(b, for (v in vars) assign(v, NA))
  a b  z  y v
1 1 3 NA NA z
2 2 2 NA NA z
3 3 1 NA NA z

您可以看到我使用此方法成功创建了列zy, 但是还有一个额外的卷v,我不知道它来自哪里。

【问题讨论】:

    标签: r dataframe variable-assignment


    【解决方案1】:

    这是一种符合原始代码精神的简单方法。

    for(v in vars) { b[[v]] <- NA }
    

    您在版本中获得额外的v 的原因是,在对within 的调用中创建的任何变量都会添加到该数据帧中,并且for 循环会创建该变量。如果你在最后删除它,它就会消失。但是,请注意您的 vars 变量包含 v 的情况。

    within(b, {for (v in vars) assign(v, NA); rm(v) })
    

    您也可以让vars 包含所有变量,并使用setdiff 获取您想要保留的变量。

    vars <- c('a','b','y','z')
    b <- data.frame(a=1:3, b=3:1)
    for(v in setdiff(vars, names(b))) { b[[v]] <- NA }
    

    【讨论】:

      【解决方案2】:

      试试这个:

      missingCols <- setdiff(vars, names(b))
      naColumn <- function(x)rep(NA, nrow(b))
      
      cbind(b, sapply(missingCols, naColumn, USE.NAMES=TRUE))
      
        a b  y  z
      1 1 3 NA NA
      2 2 2 NA NA
      3 3 1 NA NA
      

      【讨论】:

        【解决方案3】:

        你也可以试试:

        list2env(split(rep(NA,2*nrow(b)),vars),envir=.GlobalEnv)
         cbind(b,mget(vars))
        #   a b  y  z
        # 1 1 3 NA NA
        # 2 2 2 NA NA
        # 3 3 1 NA NA
        

        cbind(b,mget(setdiff(vars,names(b))))
        

        【讨论】:

          【解决方案4】:

          这里使用data.table

          require(data.table) ## 1.9.2+
          setDT(b)            ## convert data.frame to data.table
          set(b, j=vars, value=NA_integer_)
          
          #    a b  y  z
          # 1: 1 3 NA NA
          # 2: 2 2 NA NA
          # 3: 3 1 NA NA
          

          注意data.table(和:= 运算符)中的所有set* 函数都通过引用进行操作,这意味着这里没有(不必要的)复制。

          如果您想使用data.frame,只需将其转换回data.frame。在v1.9.3(目前是开发版本)中,有一个函数setDF,它被实现为通过引用从data.table返回data.frame(与传统的as.data.frame(.)函数相反,它会导致一个副本) .

          把它们放在一起(如果你想要一个 data.frame 在最后)

          ## 1.9.3
          setDF(set(setDT(b), j=vars, value=NA_integer_))
          #   a b  y  z
          # 1 1 3 NA NA
          # 2 2 2 NA NA
          # 3 3 1 NA NA
          

          再一次,没有制作(深度)副本。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-26
            • 2016-01-29
            • 2023-03-08
            • 1970-01-01
            • 2021-07-13
            • 2010-12-17
            • 2011-04-25
            相关资源
            最近更新 更多