R - 不规则元数据;从大型单列创建 df

R - Irregular metadata; create df from large single column

这个标题并没有真正反映我的问题,因为可能有几种方法可以给这只猫剥皮。但我选择了一种方法并采用了它。这就是我正在使用的:

我使用界面上的 "Send to:" 选项在 NCBI 数据库中提取了特定 study 的所有元数据,并下载了一个 .txt 文件。

我总共有大约 23k 个样本,每个样本都有多达 609 个独特的问题和答案,当以 .csv 格式读取时,问卷总计 8M+ obs of 1 variable。令我沮丧的是,元数据是不规则的。一些样本有 140 个关联的 key/value 对。其他人有 492。我在下面包含了一个 header 示例。

1: qiita_sid_10317:10317.BLANK1.6H.GUELPH
Identifiers: BioSample: SAMEA4790059; SRA: ERS2609990
Organism: metagenome
Attributes:
    /Alias="qiita_sid_10317:10317.BLANK1.6H.GUELPH"
    /description="American Gut control"
    /ENA checklist="ERC000011"
    /INSDC center alias="UCSDMI"
    /INSDC center name="University of California San Diego Microbiome Initiative"
    /INSDC first public="2018-07-13T17:03:10Z"
    /INSDC last update="2018-07-13T14:50:03Z"
    /INSDC status="public"
    /SRA accession="ERS2609990" 

我尝试过(包括但不限于):

似乎无法通过清洁步骤:

samples <- read.csv("~/biosample_result_full.txt")
samples_split <- cSplit(samples, splitCols = sample$Colname, sep = "=")
samples_split$Attributes_1 <- gsub(" ", "_", samples_split$Attributes_1)
questions <- unique(samples_split$Attributes_1)

理想情况下,每个样本和关联的元数据都将转换为行,每个 "Attribute"/问题作为列名。

非常感谢任何帮助。

我看到您链接到的网站允许选择将数据导出到 xml。我强烈建议这样做。 R 可以 hande/parse xml-files very efficient.

当我从该站点下载前三个结果到文件 biosample_result.xml 时,使用 xml2-package

很容易处理
library( xml2 )
library( magrittr )

doc <- read_xml( "./biosample_result.xml")
#gret all BioSample nodes
BioSample.Nodes <- xml_find_all( doc, "//BioSample")
#build a data.frame
data.frame( 
  sample_name = xml_find_first( BioSample.Nodes , ".//Id[@db='SRA']") %>% xml_text(),
  stringsAsFactors = FALSE )

#   sample_name
# 1  ERS2609990
# 2  ERS2609989
# 3  ERS2609988

因此,如果您可以使用 XML,您只需要使用正确的 xpath 语法来将您需要的 data/nodes 放入您想要的列中...
在上面的示例中,我(从每个 BioSample 节点)提取了属性 db 等于 SRA 的第一个 ID 节点,并将结果存储在 co0lumn sample_name.

仍然假设您可以使用 xml-数据。 如果您正在将所有属性锁定到一个 df 中,则需要 purrr 中的函数,因此只需加载整个 tidyverse

library( tidyverse )
df <- xml_find_all( doc, "//BioSample")  %>% 
  map_df(~{
    set_names(
      xml_find_all(.x, ".//Attribute") %>% xml_text(),
      xml_find_all(.x, ".//Attribute") %>% xml_attr( "attribute_name" )

    ) %>% 
      as.list() %>%  
      flatten_df() 
  })

会产生这样的 df