通过rownames合并不均匀数据帧列表

时间:2018-04-09 08:33:17

标签: r

我在列表中有几个数据帧,我想合并到一个大数据帧中。实际列表包含了这些数据帧的几个部分,因此我正在寻找一个优选的有效解决方案。

该列表与此类似:

v <- data.frame(answer = c(1,1,1))
rownames(v) <- c("A","B","C")
w <- data.frame(answer = c(1,0,0))
rownames(w) <- c("A","B","D")
x <- data.frame(answer = c(1,1,1))
rownames(x) <- c("A","B","C")
y <- data.frame(answer = c(0,0,0))
rownames(y) <- c("A","C","D")
z <- data.frame(answer = c(0,0,0,1))
rownames(z) <- c("A","B","C","D")
l <- list(v,w,x,y,z)
names(l) <- c("V","W","X","Y","Z")

最终输出应如下所示:

    v    W    X    Y    Z
A   1    1    1    0    0
B   1    0    1    NA   0
C   1    NA   1    0    0
D   NA   0    NA   0    1

我已尝试过的内容(如果您已经有了可行的解决方案,请随意忽略此部分)

  df <- data.frame(matrix(unlist(l), nrow=length(l), byrow=T),stringsAsFactors=FALSE)

df <- do.call(rbind.data.frame, l)

df<- rbindlist(l) (from library("data.frame"))

如果所有数据帧具有相同的长度和相同的顺序,那么所有这些都会松散rownames中包含的信息。

对我的实际数据有用的唯一一个是:

df<- suppressWarnings(Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = 
"answer", all = TRUE),l))

但我无法使其与我的示例列表一起工作,即使它工作起来也非常不合理,并且一旦列表变长,就会花费很长时间。

3 个答案:

答案 0 :(得分:4)

我们创建一个行名列,然后进行连接。我们使用list遍历map,通过rownames_to_column reduce创建一个包含full_joinby的行名称列到单个数据集行名称和rename列名称(如果需要)

library(tidyverse)
l %>% 
   map( ~ .x %>%
             rownames_to_column('rn')) %>%
   reduce(full_join, by = 'rn') %>%
   rename_at(2:6, ~ names(l))
#  rn  V  W  X  Y Z
#1  A  1  1  1  0 0
#2  B  1  0  1 NA 0
#3  C  1 NA  1  0 0
#4  D NA  0 NA  0 1

或另一种选择是bind_rows然后spread

l %>%
  map(rownames_to_column, 'rn') %>% 
  bind_rows(.id = 'grp') %>%
  spread(grp, answer)
#  rn  V  W  X  Y Z
#1  A  1  1  1  0 0
#2  B  1  0  1 NA 0
#3  C  1 NA  1  0 0
#4  D NA  0 NA  0 1

答案 1 :(得分:4)

以下是使用mergeReduce的基本R解决方案:

df <- Reduce(
    function(x, y) merge(x, y, by = "id", all = T),
    lapply(l, function(x) { x$id <- rownames(x); x }))
colnames(df) <- c("id", names(l))
#  id  V  W  X  Y Z
#1  A  1  1  1  0 0
#2  B  1  0  1 NA 0
#3  C  1 NA  1  0 0
#4  D NA  0 NA  0 1

答案 2 :(得分:2)

使用与已经适用的类似的东西的一种方法是首先将rownames声明为变量,然后重命名数据框的列以匹配列表中的名称,然后合并。 / p>

df_l <- l %>% Map(setNames, ., names(.)) %>%
  map(~mutate(., r=rownames(.))) %>% 
  Reduce(function(dtf1,dtf2) full_join(dtf1,dtf2,by="r"), .)

rownames(df_l) <- df_l$r
df_l$r <- NULL

说实话,我不确定它是否有效,而且就像你说的那样,随着名单的增长可能需要很长时间。