深度嵌套向量列表的tidyr融合(melt)等效于reshape2::melt()

4
使用reshape2,可以轻松将嵌套的向量列表转换为包含每个值的原始列表位置信息的长数据框。
# generate nested list of depth 3 with 2 branches at each level
n_l <- purrr::array_tree(
  array(1:2^3, rep_len(2, 3))
)

m_n_l <- reshape2::melt(n_l)

# this provides a df of values where original list position is labelled using 
# [n_dimensions] columns each with [n_branches] values. yay! that's what I want
m_n_l

#    value L3 L2 L1
# 1      1  1  1  1
# 2      5  2  1  1
# 3      3  1  2  1
# 4      7  2  2  1
# 5      2  1  1  2
#        ...

# [reshape2::melt() also handles the case where leaf node vectors have 
# arbitrary number of elements]
reshape2::melt(rapply(n_l, function(x) x * 1:sample(1:3, 1)))

reshape2 已经被弃用,用户被鼓励使用 tidyr。但是,我找不到 tidyr 的方法来复制 reshape2::melt() 上面的功能。 pivot_longer()hoist()unnest() 看起来像是替换 melt() 的函数,但它们似乎只适用于 data.frames 或 data.frames 列表的特定情况。

tidyr 可以做到这一点吗?

1个回答

3

使用rrapply的一种选项可能是:

Reduce(rbind, rrapply(n_l, f = function(x, .xpos) c(.xpos, x), how = "flatten"))

     [,1] [,2] [,3] [,4]
init    1    1    1    1
        1    1    2    5
        1    2    1    3
        1    2    2    7
        2    1    1    2
        2    1    2    6
        2    2    1    4
        2    2    2    8

但如果您正在寻找特定的tidyverse选项,那么一个不太紧凑的选项可能是:

enframe(n_l) %>%
 mutate(value = map(value, ~ enframe(., name = "name2"))) %>%
 unnest(value) %>%
 mutate(value = map(value, ~ enframe(., name = "name3"))) %>%
 unnest(value) %>%
 mutate(value = unlist(value))

   name name2 name3 value
  <int> <int> <int> <int>
1     1     1     1     1
2     1     1     2     5
3     1     2     1     3
4     1     2     2     7
5     2     1     1     2
6     2     1     2     6
7     2     2     1     4
8     2     2     2     8

使用专用选项 rrapply(n_l, how = "melt") 可能更有效,只有当位置列仍需要转换为整数时才需要进行转换(这里提供了一些基准测试 https://jorischau.github.io/rrapply/articles/articles/efficient-melting-unmelting.html)。 - Joris C.
1
@Joris C. 可能将其转换为整数会使最终效率降低。但总体而言,您开发的这个库是一个非常好的选择 :) - tmfmnk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接