R; DPLYR:将数据帧列表转换为单个有组织的数据帧

R; DPLYR: Convert a list of dataframes into a single organized dataframe

我有一个包含多个条目的列表,示例条目如下所示:

> head(gene_sets[[1]])
     patient Diagnosis Eigen_gene ENSG00000080824 ENSG00000166165 ENSG00000211459 ENSG00000198763 ENSG00000198938 ENSG00000198886
1 689_120604        AD -0.5606425           50137           38263          309298          528233          523420          730537
2 412_120503        AD  0.9454632           44536           23333          404316          730342          765963         1168123
3 706_120605        AD  0.6061834           16647           22021          409498          614314          762878         1171747
4 486_120515        AD  0.8164779           21871            9836          518046          697051          613621         1217262
5 469_120514        AD  0.5354927           33460           11651          468223          653745          608259         1115973
6 369_120502        AD -0.8363372           32168           44760          271978          436132          513194          784537

对于这些条目,前三列总是一致的,总列数不同。

我想做的是将整个列表转换为数据框。我需要保留的信息是 set_index 作为列表中条目的索引,然后是 Eigen_gene 之外的所有列名,直到最后一列。

我可以想到使用循环的解决方案,但我想要 dplyr/reshape 解决方案。

澄清一下,如果我们有一个看起来像这样的假输入:

> list(data.frame(patient= c(1,2,3), Diagnosis= c("AD","Control", "AD"), Eigen_gene= c(1.1, 2.3, 4.3), geneA= c(1,1,1), geneC= c(2,1,3), geneB= c(2,39,458)))
[[1]]
  patient Diagnosis Eigen_gene geneA geneC geneB
1       1        AD        1.1     1     2     2
2       2   Control        2.3     1     1    39
3       3        AD        4.3     1     3   458

所需的输出如下所示(我只显示了输入的第一个列表条目的示例,输出显示了列表中其他条目的格式):

> data.frame(set_index= c(1,1,1,2,2,2,3,3), gene= c("geneA", "geneC", "geneB", "geneF", "geneE", "geneH", "geneT", "geneZ"))
  set_index  gene
1         1 geneA
2         1 geneC
3         1 geneB
4         2 geneF
5         2 geneE
6         2 geneH
7         3 geneT
8         3 geneZ

谢谢!

这是 tidyversepurrr 的解决方案。我扩展了示例输入以生成示例输出。这里的关键函数是imap,也就是shorthand for map2(x, seq_along(x))。有关更多信息,请参阅 help。我们想要做的是将一个函数应用于列表 其索引中的每个数据帧。所以我们使用函数 ~ tibble(set_index = .y, gene = colnames(.x[4:ncol(.x)])).

  • ~.x.ypurrr shorthands for function(x, y)xy.这让我们可以紧凑地引用函数的参数。参见 ?map2
  • set_index = .y 创建第一列并用当前数据帧的索引填充它(它被有用地重复以达到正确的长度)
  • gene = colnames(.x[4:ncol(.x)])) 从基因名称向量创建第二列。 colnames 获取数据框的变量名称,但我们进行子集化以排除前三个。
  • 如果我们只有 imap,我们会得到一个数据帧列表。 imap_dfr 只是获取该列表并将它们绑定在一起作为行,从而产生我们想要的输出。 (相当于之后调用bind_rows
library(tidyverse)
gene_list <- list(
  data.frame(
    patient= c(1,2,3),
    Diagnosis= c("AD","Control", "AD"),
    Eigen_gene= c(1.1, 2.3, 4.3),
    geneA= c(1,1,1),
    geneC= c(2,1,3),
    geneB= c(2,39,458)
  ),
  data.frame(
    patient= c(1,2,3),
    Diagnosis= c("AD","Control", "AD"),
    Eigen_gene= c(1.1, 2.3, 4.3),
    geneF= c(1,1,1),
    geneE= c(2,1,3),
    geneH= c(2,39,458)
  ),
  data.frame(
    patient= c(1,2,3),
    Diagnosis= c("AD","Control", "AD"),
    Eigen_gene= c(1.1, 2.3, 4.3),
    geneT= c(1,1,1),
    geneZ= c(2,1,3)
  )
)

output <- gene_list %>%
  imap_dfr(~ tibble(set_index = .y, gene = colnames(.x[4:ncol(.x)])))
output
#> # A tibble: 8 x 2
#>   set_index gene 
#>       <int> <chr>
#> 1         1 geneA
#> 2         1 geneC
#> 3         1 geneB
#> 4         2 geneF
#> 5         2 geneE
#> 6         2 geneH
#> 7         3 geneT
#> 8         3 geneZ

reprex package (v0.2.0) 创建于 2018-03-02。