如何以编程方式在数据框中分配一堆变量

时间:2014-07-01 10:49:11

标签: r dataframe variable-assignment

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

然而,当我使用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,我不知道它来自哪里。

4 个答案:

答案 0 :(得分:2)

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

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 }

答案 1 :(得分:1)

试试这个:

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

答案 2 :(得分:1)

您也可以尝试:

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

答案 3 :(得分:1)

此处使用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

请注意set*(和data.table运算符)中的所有:=函数都按引用进行操作,这意味着此处没有(不必要的)副本。

如果您想使用data.frame,则可以将其转换回data.frame。在v1.9.3(当前正在开发的版本)中,有一个函数setDF被实现为通过引用从data.frame返回data.table(相反)传统的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

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