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(.))))