xml-анализатор в R с иерархическими узлами, тегами и значениями

Я пытаюсь разобрать sample_attributes (желательно все) из следующего XML-файла. Перепробовал несколько вещей, но XML объединяется в один узел:

xml.url <- "http://www.ebi.ac.uk/ena/data/view/ERS445758&display=xml"
xmlfile <- xmlTreeParse(xml.url)
xmltop = xmlRoot(xmlfile)
IBDcat <- xmlSApply(xmltop, function(x) xmlSApply(x, xmlValue))

Также попробовал решения, упомянутые здесь: Как анализировать фрейм данных XML в R и как создать фрейм данных R из XML-файла, но когда я пытаюсь что-то вроде:

data <- xmlParse("http://www.ebi.ac.uk/ena/data/view/ERS445758&display=xml")
xml_data <- xmlToList(data)
xmlToDataFrame(nodes=getNodeSet(data,"/SAMPLE_ATTRIBUTE"))[c("age","sex","body site","body-mass index")]

Я получаю сообщение о том, что выбраны неопределенные столбцы

Любая помощь будет оценена спасибо!

3 ответа

Решение

По крайней мере, для второй попытки вам просто нужно было выбрать любой узел SAMPLE_ATTRIBUTE, используя //. Затем подмножество по тегу.

doc <- xmlParse(xml.url)
x <- xmlToDataFrame(getNodeSet(doc,"//SAMPLE_ATTRIBUTE"))
## OR 
xmlToDataFrame(doc["//SAMPLE_ATTRIBUTE"])
                  TAG      VALUE UNITS
1  investigation type metagenome  <NA>
2        project name       BMRP  <NA>
3 experimental factor microbiome  <NA>
4         target gene   16S rRNA  <NA>
5  target subfragment       V1V2  <NA>
...


subset(x, TAG %in% c("age","sex","body site","body-mass index") )
               TAG         VALUE UNITS
15             age            28 years
16             sex          male  <NA>
17       body site Sigmoid colon  <NA>
19 body-mass index    16.9550173  <NA>

Вот опция Tidyverse; xml2 имеет простой read_xml функция, связанная с as_list функция. purrr это пакет для манипулирования списками, который очень удобен, хотя вы можете, конечно, делать то же самое в базе R, если хотите.

library(xml2)
library(purrr)

x <- read_xml("http://www.ebi.ac.uk/ena/data/view/ERS445758&display=xml")

x_list <- as_list(x)

x_df <- x_list %>% map('SAMPLE_ATTRIBUTES') %>% flatten() %>% map_df(flatten)

x_df
#> # A tibble: 35 × 3
#>                       TAG                               VALUE UNITS
#>                     <chr>                               <chr> <chr>
#> 1      investigation type                          metagenome  <NA>
#> 2            project name                                BMRP  <NA>
#> 3     experimental factor                          microbiome  <NA>
#> 4             target gene                            16S rRNA  <NA>
#> 5      target subfragment                                V1V2  <NA>
#> 6             pcr primers                            27F-338R  <NA>
#> 7   multiplex identifiers                          TGATACGTCT  <NA>
#> 8       sequencing method                      pyrosequencing  <NA>
#> 9  sequence quality check                            software  <NA>
#> 10          chimera check ChimeraSlayer; Usearch 4.1 database  <NA>
#> # ... with 25 more rows

или вместо этого выполните подмножество в XPath:

x %>% xml_find_all('//SAMPLE_ATTRIBUTE') %>% map(as_list) %>% map_df(flatten)

который возвращает то же самое.

Немного другой подход к очень креативному @allistaire:

library(xml2)

doc <- read_xml("http://www.ebi.ac.uk/ena/data/view/ERS445758&display=xml")

xml_find_all(doc, ".//SAMPLE_ATTRIBUTE") %>% 
  map(xml_children) %>% 
  map_df(~as.list(setNames(xml_text(.), xml_name(.))))
Другие вопросы по тегам