从data.frame中提取时,用NA填充缺少的列

时间:2014-08-03 09:55:52

标签: r dataframe

我有一个函数,它将具有某些列的数据帧作为输入

columns =['a', 'b',...,'z']

现在我有一个数据框DF,其中只有少数列DF_columns = ['f', 'u', 'z']

如果列不在DF且与列DF上的['f', 'u', 'z']重合

,那么如何创建包含值为NA的所有列的数据框?

示例:

d = data.frame('g'=c(1,2,3), 's' = c(4,2,3))
columns = letters[1:21]
columns
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
[21] "u"

> d
  g s
1 1 4
2 2 2
3 3 3
> 

5 个答案:

答案 0 :(得分:3)

x.or.na <- function(x, df) if (x %in% names(df)) df[[x]] else NA
as.data.frame(Map(x.or.na, columns, list(d)))

答案 1 :(得分:2)

set.seed(42)
 DF <- setNames(as.data.frame(matrix(sample(1:15, 15, replace=TRUE), ncol=3)), c('f', 'u', 'z') )

  DF
  #  f  u  z
  #1 14  8  7
  #2 15 12 11
  #3  5  3 15
  #4 13 10  4
  #5 10 11  7

 res <- do.call(`data.frame`,lapply(split(letters[4:26], letters[4:26]), 
       function(x){x1 <- match(x, colnames(DF)); if(!is.na(x1)) DF[,x1] else NA}))

 res    
 #  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
 #1 NA NA 14 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  8 NA NA NA NA  7
 #2 NA NA 15 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 12 NA NA NA NA 11
 #3 NA NA  5 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  3 NA NA NA NA 15
 #4 NA NA 13 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 10 NA NA NA NA  4
 #5 NA NA 10 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 11 NA NA NA NA  7

使用dplyr

 library(dplyr)
   DF %>% 
   do({x1 <-data.frame(., setNames(as.list(rep(NA, sum(!letters[4:26] %in% names(DF)))), 
  setdiff(letters[4:26], names(DF))))
    x1[,order(colnames(x1))] })    
  #  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
 #1 NA NA 14 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  8 NA NA NA NA  7
 #2 NA NA 15 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 12 NA NA NA NA 11
 #3 NA NA  5 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  3 NA NA NA NA 15
 #4 NA NA 13 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 10 NA NA NA NA  4
 #5 NA NA 10 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 11 NA NA NA NA  7

答案 2 :(得分:2)

以下是一些方法及其时间。

createDF1 <- function(colVec, data)
{
    m <- matrix(, nrow = nrow(data), ncol = length(colVec), 
                dimnames = list(NULL, colVec))
    m[, names(data)] <- as.matrix(data)
    data.frame(apply(m, 2, as.numeric))
} 

createDF2 <- function(colVec, data)
{
    rr <- setNames(rep(list(rep(NA_integer_, nrow(data))), length(colVec)),  .
                   nm = colVec)
    rr[match(names(data), colVec)] <- data
    as.data.frame(rr)
}

createDF3 <- function(colVec, data)
{
    rr <- setNames(replicate(length(colVec),  
                             list(rep(NA_integer_, nrow(data)))),  
                   nm = colVec)
    rr[match(names(d), colVec)] <- data
    as.data.frame(rr)
}

创建3,000,000 x 3数据框以进行测试:

columns <- letters[1:21]
d <- data.frame(g = 1:3e6L, s = 1:3e6L, j = 1:3e6L)

运行一些测试:

system.time({ createDF1(columns, d) })
#  user  system elapsed 
# 5.022   1.023   6.054  
system.time({ createDF2(columns, d) })
#  user  system elapsed 
# 0.007   0.004   0.011 
system.time({ createDF3(columns, d) })
#  user  system elapsed 
# 0.105   0.077   0.183

在这三个中,看起来rep(list(rep(NA_integer_, nrow(data))), length(columns))是可行的方式,并从中替换值。

答案 3 :(得分:2)

使用data.table包非常简单(在语法方面)和高效(在速度方面):

require(data.table) ## 1.9.2+
setDT(d)[, setdiff(columns, names(d)) := NA] ## (1)
setcolorder(d, columns) ## (2)
setDF(d) ## (3)
  1. setDTd转换为data.table,之后我们使用:=运算符通过引用创建新列。有许多方法可以使用:=,但此处突出显示的是用例LHS := RHS。这里LHS是列名称的向量,RHS是值。在RHS上只提供一次NA,它会自动回收所有其他列。请注意,默认情况下,NA是<。>
  2. 中的逻辑类型
  3. 如果需要,您可以使用d按与列相同的顺序重新排序setcolorder列。
  4. 如果有必要,您可以使用函数data.tablesetDF 转换回data.frame ,然后再次通过引用修改对象。但它现在只在the development version v1.9.3中可用。

答案 4 :(得分:0)

设定:

set.seed(1)
DF_all <- setNames(data.frame(matrix(rnorm(5*26), nrow=5, ncol=26)), letters)
DF <- DF_all[, c('f','u','z')]

创建一个新的空数据框并填充您的列:

DF2 <- setNames(data.frame(matrix(nrow=5, ncol=26)), letters)
DF2[, c('f','u','z')] <- DF[, c('f','u','z')]

结果:

> DF2
   a  b  c  d  e           f  g  h  i  j  k  l  m  n  o  p  q  r  s  t           u  v  w  x  y           z
1 NA NA NA NA NA -0.05612874 NA NA NA NA NA NA NA NA NA NA NA NA NA NA -0.62036668 NA NA NA NA  0.71266631
2 NA NA NA NA NA -0.15579551 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0.04211587 NA NA NA NA -0.07356440
3 NA NA NA NA NA -1.47075238 NA NA NA NA NA NA NA NA NA NA NA NA NA NA -0.91092165 NA NA NA NA -0.03763417
4 NA NA NA NA NA -0.47815006 NA NA NA NA NA NA NA NA NA NA NA NA NA NA  0.15802877 NA NA NA NA -0.68166048
5 NA NA NA NA NA  0.41794156 NA NA NA NA NA NA NA NA NA NA NA NA NA NA -0.65458464 NA NA NA NA -0.32427027