R 按行名合并不均匀数据帧列表

R 按行名合并不均匀数据帧列表,r,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)) ro

我在一个列表中有几个数据帧,我想把它们合并成一个大数据帧。实际的列表包含几个数据帧,因此我正在寻找一个更有效的解决方案

列表与此类似:

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")
我已经尝试过的内容(如果您已经有了有效的解决方案,请忽略此部分)


df我们创建一个row-names列,然后进行连接。我们使用
map
循环查看
列表
,使用
rownames\u to\u列
创建一个row names列,如果需要,通过
行名和
重命名
进行
全联接,将
减少到单个数据集

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

或者另一个选项是
绑定_行
,然后
展开

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

下面是一个使用
merge
Reduce
的基本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

df这样做的一种方法是,首先将行名声明为变量,然后重命名数据帧中的列以匹配它们在列表中的名称,然后合并

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
df_l%Map(集合名,,,名称(.))%>%
映射(~mutate(,r=rownames(.))%>%
减少(函数(dtf1,dtf2)全连接(dtf1,dtf2,by=“r”),)

rownames(df_l)让别人用一行字来解决我的问题,比我写下来的时间要短,这总是让我感到惊讶,同时也让我感到惊讶。。。它确实有效。有没有办法,我可以得到一个非常简短的描述它是如何工作的?我以前没有使用过tidyverse,代码在我看来非常脚本化。我写了一些非常类似的东西,使用
imap
imap(l,~rownames\u to_column(setNames(.x,.y)))%%>%reduce(full_join)
df<- suppressWarnings(Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = 
"answer", all = TRUE),l))
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
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
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
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