使用 plyr::mutate 以矢量化方式提取列表部分?

Extract list parts in a vectorized way with plyr::mutate?

假设这段代码:

foo <- data.frame(cols_val=c("NA", "1:2:3", "4:5:6"))
library(plyr)
foo <- mutate(
  foo,
  cols_list = str_split(cols_val, ":"),
  one = cols_list[1],
  two = cols_list[2])

我希望 foo$one 成为 c(NA, "1", "4")foo$two 成为 c(NA, "2", "5")。也就是说,将 cols_val 的值拆分为数据框的各个列。

然而,cols_list 是一个列表,one == cols_list[1] 是该列表的第一个元素 (== cols_list[[1]]),而 two == cols_list[1]。所以,我不知道如何正确地对其进行矢量化。

帮忙?

> foo
  cols_val cols_list one     two
1       NA        NA  NA 1, 2, 3
2    1:2:3   1, 2, 3  NA 1, 2, 3
3    4:5:6   4, 5, 6  NA 1, 2, 3

> str(foo$cols_list)
List of 3
 $ : chr "NA"
 $ : chr [1:3] "1" "2" "3"
 $ : chr [1:3] "4" "5" "6"

我们可以使用cSplit

library(splitstackshape)
cSplit(foo, 'cols_val', ":")
#     cols_val_1 cols_val_2 cols_val_3
#1:         NA         NA         NA
#2:          1          2          3
#3:          4          5          6

默认情况下,原始列将被删除为 drop=TRUE。如果我们还需要保留原来的列,使用drop=FALSE。它还默认转换 'class'

cSplit(foo, 'cols_val', ":", drop=FALSE)
#  cols_val cols_val_1 cols_val_2 cols_val_3
#1:       NA         NA         NA         NA
#2:    1:2:3          1          2          3
#3:    4:5:6          4          5          6

您可以使用 tidyr::separate() 而不是 plyr。它做的正是你想做的。我们可以保留现有列(remove = FALSE)并将所有新列转换为适当的类型(convert = TRUE)。我只使用 fill = "left" 以避免在不使用时出现警告。我不太确定为什么会出现警告。

tidyr::separate(foo, cols_val, c("one", "two", "three"), ":", 
    remove = FALSE, convert = TRUE, fill = "left")
#   cols_val one two three
# 1       NA  NA  NA    NA
# 2    1:2:3   1   2     3
# 3    4:5:6   4   5     6