从列表列动态提取元素

问题描述 投票:0回答:1

我有以下数据:

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)

但是,显然我没有成功。

r list tidyverse
1个回答
0
投票

这是一个函数,当

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
© www.soinside.com 2019 - 2024. All rights reserved.