将嵌套在数据框中的列表中的变量转换为列

Turning variables from a list nested in a data frame into columns

我有一个 tbl_df,其中一列是命名变量列表(它们本身主要是列表)。最好使用 tidyverse 代码,我想在一组这些变量上应用一个函数,并将每个函数调用的输出转换为数据框中的一个新列(有点像 mutate_at 会,但对于这些嵌套变量)。

例如,我当前的数据类似于这样:

d <- tibble(
  l = list(list("a"=list("a1","a2","a3","a4"), 
                "b"=list("b1","b2","b3")),
           list("a"=list("x1","x2"), 
                "b"=list("y3")))
)

# A tibble: 2 x 1
  l         
  <list>    
1 <list [2]>
2 <list [2]>

我想将函数应用到 d$l 中的变量(即 ab),就像 mutate_at 给它时所做的一样多个函数,自动创建以创建它们的变量命名的新列。例如,我想应用的一个函数会将 return 它们的长度作为新列,即:

# A tibble: 2 x 3
  l            n_a   n_b
  <list>     <dbl> <dbl>
1 <list [2]>    4.    3.
2 <list [2]>    2.    1.

有谁知道这样做的简单方法吗?到目前为止,我一直在做这样的事情:

d %>%
  mutate(n_a = purrr::map(l, ~length(.$a)) %>%
           purrr::simplify(),
         n_b = purrr::map(l, ~length(.$b)) %>%
           purrr::simplify())

但我不想为 l 中的每个变量都写出来(真实数据有 ~24 个变量)。

编辑:另外,要清楚,获取长度的示例只是我想应用的 one 函数。我真的想要一种更通用的方法来对 l.[ 中变量的任意 子集 应用 arbitrary 函数=22=]

您可以使用 lengths 来提取元素的长度,而无需循环遍历它们;并使用 bind_cols 而不是 mutate 向数据框添加多列:

d %>% bind_cols(map_dfr(.$l, ~ as.list(lengths(.))))

# A tibble: 2 x 3
#  l              a     b
#  <list>     <int> <int>
#1 <list [2]>     4     3
#2 <list [2]>     2     1

或使用compose链接as.listlengths:

d %>% bind_cols(map_dfr(.$l, compose(as.list, lengths)))

# A tibble: 2 x 3
#  l              a     b
#  <list>     <int> <int>
#1 <list [2]>     4     3
#2 <list [2]>     2     1

注意此方法动态检查列表的名称,如果缺少具有特定名称的元素,结果为 NA:

d <- tibble(
    l = list(list("a"=list("a1","a2","a3","a4")),
             list("a"=list("x1","x2"), 
                  "b"=list("y3")))
)

d %>% bind_cols(map_dfr(.$l, ~ as.list(lengths(.))))

# A tibble: 2 x 3
#  l              a     b
#  <list>     <int> <int>
#1 <list [1]>     4    NA
#2 <list [2]>     2     1

您可以使用 sapply 并将结果分配给您的新列:

d[,c("a","b")] <- t(sapply(d$l,lengths))
# # A tibble: 2 x 3
#            l     a     b
#       <list> <int> <int>
# 1 <list [2]>     4     3
# 2 <list [2]>     2     1

另一种选择是使用 包中的 transposelengths 函数。

bind_cols(d, map(transpose(d$l), lengths))
# # A tibble: 2 x 3
#   l              a     b
#   <list>     <int> <int>
# 1 <list [2]>     4     3
# 2 <list [2]>     2     1