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

时间:2018-04-01 00:34:02

标签: r dataframe dplyr purrr tibble

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

例如,我目前的数据类似于:

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),就像a给出多个函数时所做的那样,自动创建以创建它们的变量命名的新列。例如,我想申请的一个函数会将它们的长度作为新列返回,即:

b

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

mutate_at

但是我不想为# A tibble: 2 x 3 l n_a n_b <list> <dbl> <dbl> 1 <list [2]> 4. 3. 2 <list [2]> 2. 1. 中的每个变量写出来(实际数据有~24个变量)。

编辑:另外,要明确的是,获取长度的示例只是一个函数,我想申请。我真的想要一种更通用的方法,在d %>% mutate(n_a = purrr::map(l, ~length(.$a)) %>% purrr::simplify(), n_b = purrr::map(l, ~length(.$b)) %>% purrr::simplify()) 中的变量的任意子集上应用任意函数。

3 个答案:

答案 0 :(得分:3)

您可以使用lengths来提取元素&#39;没有环绕它们的长度;并使用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

答案 1 :(得分:2)

另一种选择是使用包中的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

答案 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