使用R和tidyverse将整洁表格转换为深度嵌套列表

5
我将尝试使用R/tidyverse将整洁的表格(例如下面的示例)转换为嵌套列表。使用一些tidyverse技巧,我成功将其转换为深度为3的嵌套列表,但我无法想出如何进一步嵌套它们。
以下是示例输入:
library(tidyverse)
library(stringi)

n_patient = 2
n_samples = 3
n_readgroup = 4
n_mate = 2

df = data.frame(patient   = rep(rep(LETTERS[1:n_patient], n_samples),2),
                sample    = rep(rep(seq(1:n_samples), each = n_patient),2),
                readgroup = rep(stri_rand_strings(n_patient * n_samples * n_readgroup, 6, '[A-Z]'),2),
                mate      = rep(1:n_mate, each = n_patient * n_samples * n_readgroup)) %>%
  mutate(file = sprintf("%s.%s.%s_%s", patient, sample, readgroup, mate)) %>%
  arrange(file)

json = df %>% 
  nest(-patient, .key = samples) %>%
  mutate(samples = map(samples, nest, -sample, .key=readgroups))

jsonlite::toJSON(json, pretty = T)

例如,它看起来像这样

> head(df)
  patient sample readgroup mate         file
1       A      1    FCSDRJ    1 A.1.FCSDRJ_1
2       A      1    FCSDRJ    2 A.1.FCSDRJ_2
3       A      1    IAXDPR    1 A.1.IAXDPR_1
4       A      1    IAXDPR    2 A.1.IAXDPR_2
5       A      1    MLDBKZ    1 A.1.MLDBKZ_1
6       A      1    MLDBKZ    2 A.1.MLDBKZ_2

输出结果如下所示:
 [
  {
    "patient": "A",
    "samples": [
      {
        "sample": 1,
        "readgroups": [
          {
            "readgroup": "FCSDRJ",
            "mate": 1,
            "file": "A.1.FCSDRJ_1"
          },
          {
            "readgroup": "FCSDRJ",
            "mate": 2,
            "file": "A.1.FCSDRJ_2"
          },
          {
            "readgroup": "IAXDPR",
            "mate": 1,
            "file": "A.1.IAXDPR_1"
          },
          {
            "readgroup": "IAXDPR",
            "mate": 2,
            "file": "A.1.IAXDPR_2"
          },
          {
            "readgroup": "MLDBKZ",
            "mate": 1,
            "file": "A.1.MLDBKZ_1"
          },
          {
            "readgroup": "MLDBKZ",
            "mate": 2,
            "file": "A.1.MLDBKZ_2"
          },
          {
            "readgroup": "OMTWHK",
            "mate": 1,
            "file": "A.1.OMTWHK_1"
          },
          {
            "readgroup": "OMTWHK",
            "mate": 2,
            "file": "A.1.OMTWHK_2"
          }
        ]
      },
      {
        "sample": 2,
        "readgroups": [
          {
            "readgroup": "BHAEFA",
            "mate": 1,
            "file": "A.2.BHAEFA_1"
          },
          {
            "readgroup": "BHAEFA",
            "mate": 2,
            "file": "A.2.BHAEFA_2"
          },
          {
            "readgroup": "DIBRHT",
            "mate": 1,
            "file": "A.2.DIBRHT_1"
          },
          {
            "readgroup": "DIBRHT",
            "mate": 2,
            "file": "A.2.DIBRHT_2"
          },
          {
            "readgroup": "HHMOSV",
            "mate": 1,
            "file": "A.2.HHMOSV_1"
          },
          {
            "readgroup": "HHMOSV",
            "mate": 2,
            "file": "A.2.HHMOSV_2"
          },
          {
            "readgroup": "KJXTPN",
            "mate": 1,
            "file": "A.2.KJXTPN_1"
          },
          {
            "readgroup": "KJXTPN",
            "mate": 2,
            "file": "A.2.KJXTPN_2"
          }
        ]
      },
      {
        "sample": 3,
        "readgroups": [
          {
            "readgroup": "CHXJMM",
            "mate": 1,
            "file": "A.3.CHXJMM_1"
          },
          {
            "readgroup": "CHXJMM",
            "mate": 2,
            "file": "A.3.CHXJMM_2"
          },
          {
            "readgroup": "MDWRBS",
            "mate": 1,
            "file": "A.3.MDWRBS_1"
          },
          {
            "readgroup": "MDWRBS",
            "mate": 2,
            "file": "A.3.MDWRBS_2"
          },
          {
            "readgroup": "RHHKGK",
            "mate": 1,
            "file": "A.3.RHHKGK_1"
          },
          {
            "readgroup": "RHHKGK",
            "mate": 2,
            "file": "A.3.RHHKGK_2"
          },
          {
            "readgroup": "VVVJFD",
            "mate": 1,
            "file": "A.3.VVVJFD_1"
          },
          {
            "readgroup": "VVVJFD",
            "mate": 2,
            "file": "A.3.VVVJFD_2"
          }
        ]
      }
    ]
  },
  {
    "patient": "B",
    "samples": [
      {
        "sample": 1,
        "readgroups": [
          {
            "readgroup": "QAFCOS",
            "mate": 1,
            "file": "B.1.QAFCOS_1"
          },
          {
            "readgroup": "QAFCOS",
            "mate": 2,
            "file": "B.1.QAFCOS_2"
          },
          {
            "readgroup": "TJYYMQ",
            "mate": 1,
            "file": "B.1.TJYYMQ_1"
          },
          {
            "readgroup": "TJYYMQ",
            "mate": 2,
            "file": "B.1.TJYYMQ_2"
          },
          {
            "readgroup": "YMHWOI",
            "mate": 1,
            "file": "B.1.YMHWOI_1"
          },
          {
            "readgroup": "YMHWOI",
            "mate": 2,
            "file": "B.1.YMHWOI_2"
          },
          {
            "readgroup": "ZOMSBU",
            "mate": 1,
            "file": "B.1.ZOMSBU_1"
          },
          {
            "readgroup": "ZOMSBU",
            "mate": 2,
            "file": "B.1.ZOMSBU_2"
          }
        ]
      },
      {
        "sample": 2,
        "readgroups": [
          {
            "readgroup": "CZWHXP",
            "mate": 1,
            "file": "B.2.CZWHXP_1"
          },
          {
            "readgroup": "CZWHXP",
            "mate": 2,
            "file": "B.2.CZWHXP_2"
          },
          {
            "readgroup": "MIMMNH",
            "mate": 1,
            "file": "B.2.MIMMNH_1"
          },
          {
            "readgroup": "MIMMNH",
            "mate": 2,
            "file": "B.2.MIMMNH_2"
          },
          {
            "readgroup": "RCWMQY",
            "mate": 1,
            "file": "B.2.RCWMQY_1"
          },
          {
            "readgroup": "RCWMQY",
            "mate": 2,
            "file": "B.2.RCWMQY_2"
          },
          {
            "readgroup": "WDMLHE",
            "mate": 1,
            "file": "B.2.WDMLHE_1"
          },
          {
            "readgroup": "WDMLHE",
            "mate": 2,
            "file": "B.2.WDMLHE_2"
          }
        ]
      },
      {
        "sample": 3,
        "readgroups": [
          {
            "readgroup": "DWITMU",
            "mate": 1,
            "file": "B.3.DWITMU_1"
          },
          {
            "readgroup": "DWITMU",
            "mate": 2,
            "file": "B.3.DWITMU_2"
          },
          {
            "readgroup": "GCLWMA",
            "mate": 1,
            "file": "B.3.GCLWMA_1"
          },
          {
            "readgroup": "GCLWMA",
            "mate": 2,
            "file": "B.3.GCLWMA_2"
          },
          {
            "readgroup": "QZZKQB",
            "mate": 1,
            "file": "B.3.QZZKQB_1"
          },
          {
            "readgroup": "QZZKQB",
            "mate": 2,
            "file": "B.3.QZZKQB_2"
          },
          {
            "readgroup": "WJKGRB",
            "mate": 1,
            "file": "B.3.WJKGRB_1"
          },
          {
            "readgroup": "WJKGRB",
            "mate": 2,
            "file": "B.3.WJKGRB_2"
          }
        ]
      }
    ]
  }
] 

很好,但我还想根据“mate”进行嵌套(理论上可以根据任意数量的变量进行嵌套,没有深度限制)。有什么建议可以实现这一点吗?
谢谢!
1个回答

5

第一步是意识到你正在反向操作,这会得到与你的输出相同但更简单的结果:

json2 <- df %>% nest(-(1:2),.key=readgroups) %>% nest(-1,.key=samples)

然后我们可以扩展它:
json3 <- df %>% nest(-(1:3),.key=mate) %>% nest(-(1:2),.key=readgroups) %>% nest(-1,.key=samples)

jsonlite::toJSON(json3,pretty=T)

输出:

[
  {
    "patient": "A",
    "samples": [
      {
        "sample": 1,
        "readgroups": [
          {
            "readgroup": "FUPEYR",
            "mate": [
              {
                "mate": 1,
                "file": "A.1.FUPEYR_1"
              },
              {
                "mate": 2,
                "file": "A.1.FUPEYR_2"
              }
...

如果必要,可以将其概括:

vars <- names(df)[-1] # or whatever variables you want to nest, order matters!
var_pairs <- map((length(vars)-1):1,~vars[.x:(.x+1)])
json4 <- reduce(var_pairs,~{nm<-.y[1];nest(.x,.y,.key=!!enquo(nm))},.init=df)

jsonlite::toJSON(json4,pretty=T)

输出:

[
  {
    "patient": "A",
    "sample": [
      {
        "sample": 1,
        "readgroup": [
          {
            "readgroup": "FUPEYR",
            "mate": [
              {
                "mate": 1,
                "file": "A.1.FUPEYR_1"
              },
              {
                "mate": 2,
                "file": "A.1.FUPEYR_2"
              }
...

2
非常好!感谢您的回答,我想从最内层嵌套级别开始可能更有意义,尝试了一些东西,但没有成功。您的答案完美地解决了我的问题,谢谢。希望这对其他人也有用,我发现 tidyverse 中处理嵌套列表的文档/示例有点不足。 - Floris

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