我有以下数据:
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")
id x all_x
1 1358792 123 123
2 1358792 123 123
3 333482 456 456, 789
4 333482 456 456, 789
5 747475 <NA> NULL
6 747475 <NA> NULL
all_x 列是一个包含 EMPTY/NULL 值、单个字符或字符向量的列表。
我想创建一个新列(tidyverse 样式),逻辑如下:当
all_x
列有一个值或没有值时,只需从 x
中获取值。如果它有两个值(即是一个字符向量),我们要按 id
进行分组并取与行号对应的元素,即对于第一个 id 值,取字符向量的第一个元素,对于第二个 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>
我已经尝试了很多带有
if_else
、ifelse
以及取消列出和索引的变体,但由于 all_x
列的混合结构,仍然总是出现错误。
这是我得到的最接近的:
library(tidyverse)
df |>
mutate(x2 = if_else(lengths(all_x) > 1, all_x[[1]][row_number()], x), .by = id)
但是,显然我没有成功。
这是一个函数,当
x
有一个值或没有值时,它将返回 all_x
,否则从 all_x
中获取与行号对应的元素:
get_x2 <- function(x, all_x, row_num) {
if (length(all_x) <= 1) {
return(x)
}
all_x[[row_num]]
}
那么这只是按组使用
Map()
的情况:
df |>
mutate(row_num = row_number(), .by = id) |>
mutate(
x2 = Map(get_x2, x, all_x, row_num)
)
# id x all_x row_num x2
# 1 1358792 123 123 1 123
# 2 1358792 123 123 2 123
# 3 333482 456 456, 789 1 456
# 4 333482 456 456, 789 2 789
# 5 747475 <NA> NULL 1 NA
# 6 747475 <NA> NULL 2 NA