【问题标题】:Unlisting nested lists and plotting using ggplot取消列出嵌套列表并使用 ggplot 绘图
【发布时间】:2020-11-07 00:12:24
【问题描述】:

我自己制作了一个巨大的嵌套列表结构,如下所示:

str(CMaster)
List of 4
 $ :List of 6
  ..$ :List of 5
  .. ..$ :List of 15
  .. .. ..$ : num [1, 1:14] 0.144 0.2 0.256 0.352 0.446 ...
  .. .. ..$ : num [1, 1:47] 0.144 0.2 0.375 0.54 0.694 ...
etc
$ :List of 6
      ..$ :List of 1
      .. ..$ :List of 15
      .. .. ..$ : num [1, 1:14] 0.144 0.2 0.256 0.352 0.446 ...
      .. .. ..$ : num [1, 1:47] 0.144 0.2 0.375 0.54 0.694 ...

结构是固定的,但最后的 15 个列表可能会达到 150K,我需要尝试绘制这个结构。我想尝试绘制由 6 个类似列表中的每一个的 4 个变量的列表分类的箱线图,它将 15 个列表的所有数值数据浓缩到这个例子中。我需要先将其全部取消吗?有没有更简单的方法来制作一个 data.frame 或 data.table 来保留列表的名称并使它们成为绘图的因素?

dfs <- lapply(CMaster, data.frame, stringsAsFactors = FALSE)

编辑:我添加了示例代码

示例代码(接近真实结构)。

D<-list()
DNSIM<-list()
DTime<-list()
DMaster<-list()

  
for(CC in 1:4){
  for(t in 1:6){
    for(N in 1:5){
    for(i in 1:15){
      
      Dmatrix=runif(15)
      D[[i]]=Dmatrix
    }
    DTime[[t]]=D
    }
    DNSIM[[N]]=DTime
  }
  DMaster[[CC]]=DTime
 }

输入

它太大而无法复制,我的组织不允许共享指向 onedrive 的链接。有什么简单的解决方法吗?

EDIT2

tibble(lists = CMaster) %>% 
+   mutate(CleaningType = row_number()) %>% 
+   unnest_longer(lists, indices_to = "TimePoint") %>% 
+   unnest_longer(lists, indices_to = "Replicate") %>%
+   unnest_longer(lists, indices_to = "BehaviourObservation")
# A tibble: 1,800 x 5
   lists                 BehaviourObservation Replicate TimePoint CleaningType
   <list>                               <int>     <int>     <int>        <int>
 1 <dbl[,14] [1 × 14]>                      1         1         1            1
 2 <dbl[,47] [1 × 47]>                      2         1         1            1
 3 <dbl[,11] [1 × 11]>                      3         1         1            1
 4 <dbl[,40] [1 × 40]>                      4         1         1            1
 5 <dbl[,40] [1 × 40]>                      5         1         1            1
 6 <dbl[,34] [1 × 34]>                      6         1         1            1
 7 <dbl[,92] [1 × 92]>                      7         1         1            1
 8 <dbl[,31] [1 × 31]>                      8         1         1            1
 9 <dbl[,5] [1 × 5]>                        9         1         1            1
10 <dbl[,103] [1 × 103]>                   10         1         1            1
# … with 1,790 more rows

所以我尝试添加另一个子子列表,但现在出现尺寸不兼容的错误。请问大家有什么想法吗?

tibble(lists = CMaster) %>% 
+   mutate(CleaningType = row_number()) %>% 
+   unnest_longer(lists, indices_to = "TimePoint") %>% 
+   unnest_longer(lists, indices_to = "Replicate") %>%
+   unnest_longer(lists, indices_to = "BehaviourObservation") %>%
+   unnest_longer(lists, indices_to = "sub_sub_observation") 

Error: Can't combine `..1$lists` <double[,14]> and `..2$lists` <double[,47]>.
✖ Incompatible sizes 14 and 47 along axis 2.
Run `rlang::last_error()` to see where the error occurred.

【问题讨论】:

  • 你能分享一段我可以摆弄的数据(使用dput())吗?据我所知,最简单的方法是取消嵌套。可能使用purrr::map_dfr(.x, .f, ..., .id = "id_col")之类的东西。
  • 感谢您这么快回复。我已经包含了一个类似的数据结构示例,因为 dput 的输出太大而无法复制。

标签: r dataframe ggplot2 data.table


【解决方案1】:

为了完整起见,reshape2 包中的 melt() 函数有一个用于递归融合每个组件的列表的方法。

library(magrittr) # piping used to improve readability
reshape2::melt(DMaster) %>% 
  head()
       value L3 L2 L1
1 0.20653283  1  1  1
2 0.96955498  1  1  1
3 0.07924116  1  1  1
4 0.98602539  1  1  1
5 0.72998492  1  1  1
6 0.16022710  1  1  1

结合ggplot()

library(ggplot2)
reshape2::melt(DMaster) %>% 
  ggplot(aes(x = L2, y = value, group = L2)) +
  geom_boxplot() +
  facet_wrap(~ L1)

我们得到


reshape2::melt() 也有一个数组方法。因此,矩阵作为列表元素reported by the OP 的问题也被涵盖了。

这是一个双重嵌套矩阵列表的虚拟示例

rep(list(list(matrix(1:4, ncol = 2), matrix(11:19, ncol = 3))), 2) %T>% str() %>% 
  reshape2::melt()
List of 2
 $ :List of 2
  ..$ : int [1:2, 1:2] 1 2 3 4
  ..$ : int [1:3, 1:3] 11 12 13 14 15 16 17 18 19
 $ :List of 2
  ..$ : int [1:2, 1:2] 1 2 3 4
  ..$ : int [1:3, 1:3] 11 12 13 14 15 16 17 18 19
   Var1 Var2 value L2 L1
1     1    1     1  1  1
2     2    1     2  1  1
3     1    2     3  1  1
4     2    2     4  1  1
5     1    1    11  2  1
6     2    1    12  2  1
7     3    1    13  2  1
8     1    2    14  2  1
9     2    2    15  2  1
10    3    2    16  2  1
11    1    3    17  2  1
12    2    3    18  2  1
13    3    3    19  2  1
14    1    1     1  1  2
15    2    1     2  1  2
16    1    2     3  1  2
17    2    2     4  1  2
18    1    1    11  2  2
19    2    1    12  2  2
20    3    1    13  2  2
21    1    2    14  2  2
22    2    2    15  2  2
23    3    2    16  2  2
24    1    3    17  2  2
25    2    3    18  2  2
26    3    3    19  2  2

【讨论】:

    【解决方案2】:

    如果您不介意使用 tidyverse,请在下面找到一些代码,使用 tidyr::unnest_longer 将您的数据矩形化。有关如何使用 unnest_longer(以及一般如何将嵌套列表转换为 data.frames)的精彩教程,请参阅 here

    我不确定结果中observationsub_observation 之间的区别是什么,以及这个情节是否是你真正想要的。

    这在您的大型数据集上可能(太)慢了。

    library(tidyverse)
    
    df <- tibble(lists = DMaster) %>% 
      mutate(facet = row_number()) %>% 
      unnest_longer(lists, indices_to = "boxplot") %>% 
      unnest_longer(lists, indices_to = "observation") %>%
      unnest_longer(lists, indices_to = "sub_observation")
      
    df %>% 
      ggplot(aes(boxplot, lists, group = boxplot)) + 
      geom_boxplot() +
      facet_wrap(~ facet)
    

    它给出了一个带有facet(1 到 4)、boxplot(1 到 6)、observation(1 到 15)、sub_observation(1 到 15)和 lists(您的实际数值),以及以下情节:

    【讨论】:

    • 非常感谢您的帮助和链接。我发现我在最终的嵌套列表中得到了一个 double[,random length] 。但是当我添加另一个 %>% unnest_longer(lists, indices_to = "sub_sub_observation");我收到此错误:错误:无法组合 ..1$lists ..2$lists 。 ✖ 沿轴 2 的尺寸 14 和 47 不兼容。
    • 该列似乎由矩阵组成。我认为如果将它们转换为向量,它应该可以工作:%&gt;% mutate(lists = map(lists, as.vector)) %&gt;% unnest_longer(lists, indices_to = "sub_sub_observation")
    猜你喜欢
    • 2021-03-20
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2018-09-28
    • 1970-01-01
    • 2018-05-18
    • 2019-08-07
    相关资源
    最近更新 更多