rbind基于列名称并排除不匹配

时间:2015-04-06 13:53:21

标签: r

示例数据:

l <- list(x=data.frame(X1=1,X2=2,X3=3,X4=4,X5=5),
          y=data.frame(X1=6,X8=7,X4=8,X9=9,X5=10),
          z=data.frame(X1=11,X2=12,X3=13,X4=14,X5=15)
          )

我想基于预先指定的列名称rbind此列表,以便列名称(以及它的列位置匹配)。

# these are pre-defined columns names we want to `rbind` if no match, exclude the list entry
col <- c("X1","X2","X3","X4","X5") 

所需的输出应为data.frame

  X1  X2  X3  X4  X5
   1   2   3   4   5
  11  12  13  14  15
编辑:也许是这样的:

do.call(rbind, lapply(l, function(x) x[!any(is.na(match(c("X1","X2","X3","X4","X5"), names(x))))]))

4 个答案:

答案 0 :(得分:3)

以下是一种方法:

match_all_columns <- function (d, col) {
  if (all(names(d) %in% col)) {
    out <- d[, col]
  } else {
    out <- NULL
  }
  out
}
# or as a one-liner
match_all_columns <- function (d, col) if (all(names(d) %in% col)) d[col]

matched_data <- lapply(l, match_all_columns, col)
result <- do.call(rbind, matched_data)
result
#   X1 X2 X3 X4 X5
# x  1  2  3  4  5
# z 11 12 13 14 15

rbind知道忽略NULL元素。

编辑:我将d[, col]d[col]交换,因为a)它看起来更好,b)如果col只有一个元素,它会阻止数据帧被丢弃到向量,并且c我认为它在大数据帧上的性能略高一些。

答案 1 :(得分:3)

另一种可能性,允许列顺序的变化:

output.df <- data.frame(X1=numeric(), X2=numeric(), X3=numeric(),
                        X4=numeric(), X5=numeric())

for(i in seq_along(l)) {
    if(identical(sort(colnames(l[[i]])),sort(colnames(output.df))))
        output.df[nrow(output.df)+1,] <- l[[i]][,colnames(output.df)]
}

output.df

#   X1 X2 X3 X4 X5
# 1  1  2  3  4  5
# 2 11 12 13 14 15

答案 2 :(得分:2)

这似乎也有效:

do.call(rbind, lapply(l, function(x) x[!any(is.na(match(c("X1","X2","X3","X4","X5"), names(x))))]))

答案 3 :(得分:2)

使用data.table

的另一个选项
library(data.table)#v1.9.5+
na.omit(rbindlist(l, fill=TRUE)[,col, with=FALSE])
#   X1 X2 X3 X4 X5
#1:  1  2  3  4  5
#2: 11 12 13 14 15