2014-07-01 15 views
3

中指定一組變量,我想 確保每個數據幀d有所有vars指定的列。我們假設一個數據框中缺少一些列,然後我在數據框中創建這些列並將其填入NA s。如何編程給出一個字符向量<code>vars</code>和數據幀<code>d</code>列表的數據幀

不過,我這樣做是通過使用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但也有一個額外的volumn v這我不知道它來自哪裏。

回答

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

試試這個:

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

注意data.table中的所有set*函數(和:=運算符)均以引用的方式進行操作,這意味着此處沒有(不必要的)副本。

如果您想使用data.frame,則可以將其轉換回data.frame。在v1.9.3(目前的開發版本)中,有一個功能setDF,通過引用(與傳統的as.data.frame(.)函數相反,它會導致副本),通過data.table返回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 

再次,沒有(深)拷貝被做了。

相關問題