如何用tidyverse根据列表列all_x的结构生成目标新列x2?
R语言tidyverse生成新列x2的解决方案
原始数据
待处理的数据框如下:
df <- structure(list(id = c("1358792", "1358792", "333482", "333482", "747475", "747475"), x = c("123", "123", "456", "456", NA, NA), all_x = list("123", "123", c("456", "789"), c("456", "789"), list(), list())), row.names = c(NA, -6L), class = "data.frame")
需求说明
需用tidyverse风格新增列x2,规则如下:
- 若
all_x列元素长度≤1,直接取x列对应值; - 若
all_x列元素是长度为2的字符向量,按id分组后,取该组内对应行号的元素。
期望输出:
id x all_x x2 1 1358792 123 123 123 2 1358792 123 123 123 3 333482 456 456, 789 456 4 333482 456 456, 789 789 5 747475 <NA> NULL <NA> 6 747475 <NA> NULL <NA>
原代码问题
你之前尝试的代码无法得到正确结果,原因是:
all_x[[1]]取的是整个数据框all_x列的第一个元素,而非分组后每组的all_x元素;if_else更适合向量型条件判断,处理列表元素提取时,结合分组操作的case_when更适配。
正确代码
方法一:分组后提取
library(tidyverse) df |> group_by(id) |> mutate( x2 = case_when( lengths(all_x) > 1 ~ all_x[[1]][row_number()], TRUE ~ x ) ) |> ungroup()
方法二:用map2_chr结合.by参数(tidyverse 1.0.0+支持)
df |> mutate( x2 = case_when( lengths(all_x) > 1 ~ map2_chr(all_x, row_number(), ~ .x[.y]), TRUE ~ x ), .by = id )
两种方法都能生成符合要求的x2列,其中方法二无需显式分组/取消分组,更简洁。
内容的提问来源于stack exchange,提问作者deschen
相关产品推荐
相关产品推荐

