假设我有一个数据帧列表:
lst<-list(data.frame(x=1:3,y=2:4, row.names=letters[1:3]),
data.frame(z=1:4,w=2:5, row.names=letters[3:6]),
data.frame(r=2:4,s=3:5, row.names=letters[2:4]))
lst
[[1]]
x y
a 1 2
b 2 3
c 3 4
[[2]]
z w
c 1 2
d 2 3
e 3 4
f 4 5
[[3]]
r s
b 2 3
c 3 4
d 4 5
我的问题是如何将其取消列出到由行名合并的单个数据帧中,并将NA替换为0,例如:
x y z w r s
a 1 2 0 0 0 0
b 2 3 0 0 2 3
c 3 4 1 2 3 4
d 0 0 2 3 4 5
e 0 0 3 4 0 0
f 0 0 4 5 0 0
答案 0 :(得分:3)
在基数R中:
lst2 <- lapply(lst,function(x) cbind(rowname=rownames(x),x))
df1 <- Reduce(function(x,y) merge(x,y,all=T),lst2)
rownames(df1) <- df1[[1]]
df1 <- df1[-1]
df1[is.na(df1)] <- 0
df1
# x y z w r s
# a 1 2 0 0 0 0
# b 2 3 0 0 2 3
# c 3 4 1 2 3 4
# d 0 0 2 3 4 5
# e 0 0 3 4 0 0
# f 0 0 4 5 0 0
tidyverse
可以使事情更紧凑/更易读:
library(tidyverse)
lst %>%
map(rownames_to_column) %>%
reduce(full_join) %>%
`[<-`(is.na(.),value=0) %>%
column_to_rownames
# x y z w r s
# a 1 2 0 0 0 0
# b 2 3 0 0 2 3
# c 3 4 1 2 3 4
# d 0 0 2 3 4 5
# e 0 0 3 4 0 0
# f 0 0 4 5 0 0
直接按行名称合并
如果将参数merge
设置为by
或"row.names"
,则 0
支持按行名称合并,但是奇怪的是,它返回具有列{{1} },没有实际的行名。这使得Row.names
的调用比原先的调用要平滑得多,因此最终,它并没有比我原来的基本解决方案好得多,也可能更糟:
Reduce
答案 1 :(得分:3)
在我的tidyverse
中,另一种microbenchmark
解决方案比另一种解决方案要快得多(在5ms的操作中约为0.5 ms),但是我认为它有点笨拙,而且肯定不太整洁。这种方法基本上避免了通过简单地对数据帧进行行绑定,然后按行名折叠,而信任full_join
仅丢弃除一个非缺失值之外的所有值,而多次调用mean, na.rm = TRUE
的问题。
library(tidyverse)
lst <- list(
data.frame(x = 1:3, y = 2:4, row.names = letters[1:3]),
data.frame(z = 1:4, w = 2:5, row.names = letters[3:6]),
data.frame(r = 2:4, s = 3:5, row.names = letters[2:4])
)
lst %>%
map(rownames_to_column) %>%
bind_rows() %>%
group_by(rowname) %>%
summarise_all(mean, na.rm = TRUE) %>%
map_dfc(replace_na, 0)
#> # A tibble: 6 x 7
#> rowname x y z w r s
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 a 1 2 0 0 0 0
#> 2 b 2 3 0 0 2 3
#> 3 c 3 4 1 2 3 4
#> 4 d 0 0 2 3 4 5
#> 5 e 0 0 3 4 0 0
#> 6 f 0 0 4 5 0 0
由reprex package(v0.2.0)于2018-06-22创建。