使用imap合并两个命名列表中的多个tibble:如何正确子集化以避免异常列名
解决
dplyr::bind_rows合并命名列表tibble时的列名异常问题 这个问题的核心原因是你使用了list2[.y]来提取目标tibble——[操作符返回的是带原结构的子列表(长度为1),而非单个tibble对象。当这个子列表带有名称时,bind_rows会自动把列表名作为前缀添加到列名上,就出现了你看到的X$a这类奇怪的命名。
两种快速解决办法
方法1:用[[代替[提取单个tibble
[[操作符会直接返回列表中的单个元素(这里就是tibble),而不是子列表,bind_rows可以正常识别并合并:
library(tidyverse) # 保留原命名列表 list1 <- list( tibble(a = 1:4, b = LETTERS[1:4]), tibble(a = 5:8, b = LETTERS[5:8]), tibble(a = 9:12, b = LETTERS[9:12]) ) %>% set_names(c("X","Y","Z")) list2 <- list( tibble(a = 3:6, b = LETTERS[3:6], c = 3:6 / 2), tibble(a = 7:10, b = LETTERS[7:10], c = 7:10 / 2), tibble(a = 11:14, b = LETTERS[11:14], c = 11:14 / 2) ) %>% set_names(c("X","Y","Z")) # 修正后的代码:用[[提取单个tibble list1 %>% imap(~ { .x %>% bind_rows(list2[[.y]]) })
运行后会得到正常合并的结果,同时完全保留原列表的名称:
#> $X #> # A tibble: 8 × 3 #> a b c #> <int> <chr> <dbl> #> 1 1 A NA #> 2 2 B NA #> 3 3 C NA #> 4 4 D NA #> 5 3 C 1.5 #> 6 4 D 2 #> 7 5 E 2.5 #> 8 6 F 3 #> #> $Y #> # A tibble: 8 × 3 #> a b c #> <int> <chr> <dbl> #> 1 5 E NA #> 2 6 F NA #> 3 7 G NA #> 4 8 H NA #> 5 7 G 3.5 #> 6 8 H 4 #> 7 9 I 4.5 #> 8 10 J 5 #> #> $Z #> # A tibble: 8 × 3 #> a b c #> <int> <chr> <dbl> #> 1 9 I NA #> 2 10 J NA #> 3 11 K NA #> 4 12 L NA #> 5 11 K 5.5 #> 6 12 L 6 #> 7 13 M 6.5 #> 8 14 N 7
方法2:用pluck()函数提取元素
如果你更喜欢purrr风格的函数,可以用pluck()代替[[,效果完全一致:
list1 %>% imap(~ { .x %>% bind_rows(list2 %>% pluck(.y)) })
为什么unname()后能正常工作?
当你给列表unname()之后,list2[.y]返回的子列表没有了名称,bind_rows就不会添加前缀列名,但本质上你还是在合并“子列表”而非单个tibble,这种做法不如直接提取单个元素高效,也没必要丢掉列表名称。
内容的提问来源于stack exchange,提问作者jatx50
相关产品推荐
相关产品推荐

