使用list_cbind()合并行数不同的tibble列表报错的解决方法
合并行数不同的tibble列表
当用map()生成的tibble列表中行数不一致时,list_cbind()会因无法循环补齐报错,示例场景及错误如下:
library(tidyverse) a1 <- tibble(name1 = c(1,2,3)) a2 <- tibble(name2 = c(1,2,3)) a3 <- tibble(name3 = c(1,2)) A <- list(a1, a2, a3) list_cbind(A)
报错信息:
Error in `list_cbind()`: ! Can't recycle `..1` (size 3) to match `..3` (size 2). Run `rlang::last_error()` to see where the error occurred.
list_cbind()的size参数无法解决此问题,因为它要求所有输入的行数必须能被指定size整除,否则仍会触发错误。
方法1:添加行索引后全连接
给每个tibble添加行号,通过行号做全连接,缺失行自动填充NA:
# 为每个tibble添加行索引 A_with_id <- map(A, ~ mutate(.x, id = row_number())) # 依次全连接,最后移除行索引列 result <- reduce(A_with_id, full_join, by = "id") %>% select(-id) # 输出结果 result #> # A tibble: 3 × 3 #> name1 name2 name3 #> <dbl> <dbl> <dbl> #> 1 1 1 1 #> 2 2 2 2 #> 3 3 3 NA
方法2:长格式转宽格式
先将所有tibble合并为长格式,再转换为宽格式,同样自动补NA:
# 转换为带列名和行号的长格式 long_data <- imap_dfr(A, ~ tibble( value = .x[[1]], col_name = names(.x), id = row_number() )) # 转宽格式 result2 <- long_data %>% pivot_wider(names_from = col_name, values_from = value) %>% select(-id) result2 #> # A tibble: 3 × 3 #> name1 name2 name3 #> <dbl> <dbl> <dbl> #> 1 1 1 1 #> 2 2 2 2 #> 3 3 3 NA
方法3:截断到最短行数
如果不需要保留多余行,可将所有tibble截断到列表中最短的行数,再用list_cbind()合并:
# 获取列表中最短的行数 min_rows <- min(map_int(A, nrow)) # 截断每个tibble到min_rows行 A_truncated <- map(A, ~ slice_head(.x, n = min_rows)) # 合并 result_truncated <- list_cbind(A_truncated) result_truncated #> # A tibble: 2 × 3 #> name1 name2 name3 #> <dbl> <dbl> <dbl> #> 1 1 1 1 #> 2 2 2 2
内容的提问来源于stack exchange,提问作者GeorgeM
相关产品推荐
相关产品推荐

