tidyverse:绑定相同维度的列表元素
使用tidyverse:绑定相同维度的列表元素,r,dplyr,tidyverse,reduce,purrr,R,Dplyr,Tidyverse,Reduce,Purrr,使用reduce(bind\u cols),可以组合相同维度的列表元素。但是,我想知道如何从可能具有不同维度元素的列表中只组合相同维度(可能以某种方式指定维度)的元素 library(tidyverse) df1 <- data.frame(A1 = 1:10, A2 = 10:1) df2 <- data.frame(B = 11:30) df3 <- data.frame(C = 31:40) ls1 <- list(df1, df3) ls1 [[1]]
reduce(bind\u cols)
,可以组合相同维度的列表元素。但是,我想知道如何从可能具有不同维度元素的列表中只组合相同维度(可能以某种方式指定维度)的元素
library(tidyverse)
df1 <- data.frame(A1 = 1:10, A2 = 10:1)
df2 <- data.frame(B = 11:30)
df3 <- data.frame(C = 31:40)
ls1 <- list(df1, df3)
ls1
[[1]]
A1 A2
1 1 10
2 2 9
3 3 8
4 4 7
5 5 6
6 6 5
7 7 4
8 8 3
9 9 2
10 10 1
[[2]]
C
1 31
2 32
3 33
4 34
5 35
6 36
7 37
8 38
9 39
10 40
ls1 %>%
reduce(bind_cols)
A1 A2 C
1 1 10 31
2 2 9 32
3 3 8 33
4 4 7 34
5 5 6 35
6 6 5 36
7 7 4 37
8 8 3 38
9 9 2 39
10 10 1 40
ls2 <- list(df1, df2, df3)
ls2
[[1]]
A1 A2
1 1 10
2 2 9
3 3 8
4 4 7
5 5 6
6 6 5
7 7 4
8 8 3
9 9 2
10 10 1
[[2]]
B
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
10 20
11 21
12 22
13 23
14 24
15 25
16 26
17 27
18 28
19 29
20 30
[[3]]
C
1 31
2 32
3 33
4 34
5 35
6 36
7 37
8 38
9 39
10 40
ls2 %>%
reduce(bind_cols)
Error: Can't recycle `..1` (size 10) to match `..2` (size 20).
Run `rlang::last_error()` to see where the error occurred.
库(tidyverse)
df1一个选项可以是:
map(split(lst, map_int(lst, NROW)), bind_cols)
$`10`
A1 A2 C
1 1 10 31
2 2 9 32
3 3 8 33
4 4 7 34
5 5 6 35
6 6 5 36
7 7 4 37
8 8 3 38
9 9 2 39
10 10 1 40
$`20`
B
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
10 20
11 21
12 22
13 23
14 24
15 25
16 26
17 27
18 28
19 29
20 30
这里还有另一个tidyverse
选项
我们基于行号()
,在每个data.frame
中创建一个虚拟ID,然后通过虚拟ID连接所有data.frame
,然后删除虚拟ID
ls2 %>%
map(., ~mutate(.x, id = row_number())) %>%
reduce(full_join, by = "id") %>%
select(-id)
这给了我们:
A1 A2 B C
1 1 10 11 31
2 2 9 12 32
3 3 8 13 33
4 4 7 14 34
5 5 6 15 35
6 6 5 16 36
7 7 4 17 37
8 8 3 18 38
9 9 2 19 39
10 10 1 20 40
11 NA NA 21 NA
12 NA NA 22 NA
13 NA NA 23 NA
14 NA NA 24 NA
15 NA NA 25 NA
16 NA NA 26 NA
17 NA NA 27 NA
18 NA NA 28 NA
19 NA NA 29 NA
20 NA NA 30 NA
你可以用-
n <- 1:max(sapply(ls2, nrow))
res <- do.call(cbind, lapply(ls2, `[`, n, ,drop = FALSE))
res
# A1 A2 B C
#1 1 10 11 31
#2 2 9 12 32
#3 3 8 13 33
#4 4 7 14 34
#5 5 6 15 35
#6 6 5 16 36
#7 7 4 17 37
#8 8 3 18 38
#9 9 2 19 39
#10 10 1 20 40
#NA NA NA 21 NA
#NA.1 NA NA 22 NA
#NA.2 NA NA 23 NA
#NA.3 NA NA 24 NA
#NA.4 NA NA 25 NA
#NA.5 NA NA 26 NA
#NA.6 NA NA 27 NA
#NA.7 NA NA 28 NA
#NA.8 NA NA 29 NA
#NA.9 NA NA 30 NA
我们还可以从基本R使用Reduce
函数:
lst <- list(df1, df2, df3)
# First we create id number for each underlying data set
lst |>
lapply(\(x) {x$id <- 1:nrow(x);
x
}
) -> ls2
Reduce(function(x, y) if(nrow(x) == nrow(y)){
merge(x, y, by = "id")
} else {
x
}, ls2)
id A1 A2 C
1 1 1 10 31
2 2 2 9 32
3 3 3 8 33
4 4 4 7 34
5 5 5 6 35
6 6 6 5 36
7 7 7 4 37
8 8 8 3 38
9 9 9 2 39
10 10 10 1 40
lst
lapply(\(x){x$id ls2
如果(nrow(x)=nrow(y))减少(函数(x,y)){
合并(x,y,by=“id”)
}否则{
x
},ls2)
id A1 A2 C
1 1 1 10 31
2 2 2 9 32
3 3 3 8 33
4 4 4 7 34
5 5 5 6 35
6 6 6 5 36
7 7 7 4 37
8 8 8 3 38
9 9 9 2 39
10 10 10 1 40
我们可以使用cbind.fill
从rowr
library(rowr)
do.call(cbind.fill, c(ls2, fill = NA))
使用tapply
+sapply
tapply(
ls2,
sapply(ls2, nrow),
function(x) do.call(cbind, x)
)
给予
如果要组合列表中的类似元素,也可以在reduce
中使用if
(案例:当列表中的第一项具有优先级时)
df1 4 7 34
#> 5 5 6 35
#> 6 6 5 36
#> 7 7 4 37
#> 8 8 3 38
#> 9 9 2 39
#> 10 10 1 40
由(v2.0.0)于2021-06-09创建也许您可以用理想的ls2%>%reduce(bind_cols)输出更新问题
?我不明白你的问题。你的预期输出是什么样子的?请查看我对@ianCampbell的编辑以了解我的实际列表,我收到了以下错误:错误:结果1必须是一个整数,长度不为0
。请想一想。你有没有可能有一个空列表?将nrow
更改为nrow
在map_int(lst,NROW)
中也适用于我的实际列表。谢谢,这也适用于空列表。@AnoushiravanR将类似于公认的解决方案,即获取行数并按行数拆分。在base R
中,它将使用lappy(拆分(ls2,sappy(ls2,NROW)),函数(x)do.call(cbind,x))
我没有收到。您可以使用分组
,绑定行
您知道这么多包,尊敬的!)
tapply(
ls2,
sapply(ls2, nrow),
function(x) do.call(cbind, x)
)
$`10`
A1 A2 C
1 1 10 31
2 2 9 32
3 3 8 33
4 4 7 34
5 5 6 35
6 6 5 36
7 7 4 37
8 8 3 38
9 9 2 39
10 10 1 40
$`20`
B
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
10 20
11 21
12 22
13 23
14 24
15 25
16 26
17 27
18 28
19 29
20 30