2016-07-25 100 views
1

如果有人能告诉我如何从xml中提取数据到R,我将不胜感激。下面是一个来自我的xml文件的1个化合物的例子,但真正的文件包含几百个这样的化合物。 我知道有几个类似的问题发布,但到目前为止,我还没有能够开发以前的答案,以满足我的要求。例如,我可以使用从xml提取数据到数据框

doc <- xmlParse("isotope information.xml") 
xmlToDataFrame(
    getNodeSet(doc, "//isotope"), 
    colClasses=c("character","numeric") 
) 

以提取很长的“MZ”和“丰度”值的列表中,但这些都没有用,除非它们被连接到相关的化合物和样品等。而且此方法不如果我进一步尝试树,似乎没有工作,我认为部分原因是因为名称中信息和/或空间的不同类型?

任何帮助非常感谢。我是R新手,直到开始使用此文件时才听说过xPath!

<?xml version="1.0" encoding="utf-8"?> 
<compounds> 
    <compound identifier="24.24_355.2087m/z" retentionTime="24.2409"> 
    <statistics> 
     <anova>0.0013522641768629606</anova> 
     <maxFoldChange>18.444703223432118</maxFoldChange> 
     <mean lowest="Group A" highest="Group B" /> 
    </statistics> 
    <condition name="Group A"> 
     <sample name="ACU_S1_D1_MSonly" normalizedAbundance="0.16176030585271"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.131459235488</mz> 
      <abundance>0.115052197015018</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S4_D1_MSonly" normalizedAbundance="0.648153833258576"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.210174560547</mz> 
      <abundance>0.45734640955925</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S7_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S9_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S10_D1_MSonly" normalizedAbundance="1.40543741447065"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.222929359468</mz> 
      <abundance>0.998472798001696</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.785247802734</mz> 
      <abundance>0.00450361325390688</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S11_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S14_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S17_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
    </condition> 
    <condition name="Group B"> 
     <sample name="ACU_S2_D1_MSonly" normalizedAbundance="8.08281443709004"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.217085869147</mz> 
      <abundance>6.34168970755279</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.720179758869</mz> 
      <abundance>1.01208656740541</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S3_D1_MSonly" normalizedAbundance="1.74468788905785"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.236865028724</mz> 
      <abundance>1.25719554540164</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S5_D1_MSonly" normalizedAbundance="1.20519908118674"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.221413778655</mz> 
      <abundance>0.693123193025995</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S6_D1_MSonly" normalizedAbundance="11.8264838326202"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.208446325351</mz> 
      <abundance>5.67846393951768</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.712529790798</mz> 
      <abundance>0.718700468540192</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S12_D1_MSonly" normalizedAbundance="6.62039336582067"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.195225774627</mz> 
      <abundance>4.80023810084345</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S13_D1_MSonly" normalizedAbundance="9.10340543014277"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.231293658837</mz> 
      <abundance>8.75476514173928</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.73683673041</mz> 
      <abundance>1.118534732035</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S15_D1_MSonly" normalizedAbundance="0"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.206065493636</mz> 
      <abundance>0</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
     <sample name="ACU_S16_D1_MSonly" normalizedAbundance="2.27851790546988"> 
     <adduct charge="2"> 
      <isotope> 
      <mz>355.242192813064</mz> 
      <abundance>1.25391817825056</abundance> 
      </isotope> 
      <isotope> 
      <mz>355.704849713088</mz> 
      <abundance>0</abundance> 
      </isotope> 
     </adduct> 
     </sample> 
    </condition> 
    </compound> 

UPDATE原始发帖 嗨再次,为您最初的帮助,但许多感谢使用XML和XML2我试图阐述的答案得到我需要的数据帧,我还在挣扎,所以我添加更多信息...

我已经确定了XML文档的结构之中:

# load necessary package(s) 
library(XML) 

# parse the xml file in to an R object call xmlfile 
xmlfile = xmlTreeParse("QI isotope information.xml") 


# check that the xmlfile object is recognised as an xml class 
class(xmlfile) # the output should be: "XMLInternalDocument" "XMLAbstractDocument" 

# find the root of the xml file 
xmltop = xmlRoot(xmlfile) 
class(xmltop) # "XMLInternalElementNode" "XMLInternalNode"  "XMLAbstractNode" 
xmlName(xmltop) # "compounds" 
xmlSize(xmltop) # 4278 

# the root of the xmlfile is "compounds" and it has 4278 children 
# to view the content of the first child use: 
xmltop[[1]] 

# this contains all of the information from a unique compound identifier: 
# <compound identifier="106.16_603.4571m/z" retentionTime="106.16268333333333"> 
# <statistics> 
# <anova>1.1102230246251565E-16</anova> 
# <maxFoldChange>321.93091917042375</maxFoldChange> 
# <mean lowest="D9" highest="D1"/> 
# </statistics> 
# <condition name="D1"> 
# <sample name="ACU_S1_D1_MSonly" normalizedAbundance="2016.23926856296"> 
#  <adduct charge="1"> 
#  <isotope> 
#   <mz>603.509454467435</mz> 
#   <abundance>1017.28655636311</abundance> 
#  </isotope> 
#  <isotope> 
#   <mz>604.51484984744</mz> 
#   <abundance>346.272257983685</abundance> 
#  </isotope> 
#  <isotope> 
#   <mz>605.519216627667</mz> 
#   <abundance>64.8701884746552</abundance> 
#  </isotope> 
#  </adduct> 
# </sample> 
# N.B. this list is repeated for each sample name, in this case n=64 samples 

xmlSize(xmltop[[1]]) # gives the number of nodes under the root, in this case n=5 
xmlSApply(xmltop[[1]], xmlName) # gives the names of these 5 nodes 
# statistics condition condition condition condition 
# "statistics" "condition" "condition" "condition" "condition" 
xmlSApply(xmltop[[1]], as.list) 

xmltop[[1]][[1]] # takes you to the statistics output: 
# <statistics> 
# <anova>1.1102230246251565E-16</anova> 
# <maxFoldChange>321.93091917042375</maxFoldChange> 
# <mean lowest="D9" highest="D1"/> 
# </statistics> 

xmltop[[1]][[2]] # takes you to the "condition" level, i.e. condition name="D1" 

xmltop[[1]][[2]][[1]] # takes you to the "sample" level, i.e. sample name="ACU_S1_D1_MSonly" 

xmltop[[1]][[2]][[2]] # takes you to the "sample" level number 2, i.e. sample name="ACU_S2_D1_MSonly" 

xmltop[[1]][[2]][[1]][[1]] # takes you to the "charge" level, i.e. adduct charge="1" 

xmltop[[1]][[2]][[1]][[1]][[1]] # takes you to the "isotope" level, which includes m/z and abundance 

# incrementing the last index number takes you to each isotope for that compound 
# for example: 

xmltop[[1]][[2]][[1]][[1]][[1]][[1]] # <mz>603.509454467435</mz> 
xmltop[[1]][[2]][[1]][[1]][[1]][[2]] # <abundance>1017.28655636311</abundance> 
xmltop[[1]][[2]][[1]][[1]][[2]][[1]] # <mz>604.51484984744</mz> 
xmltop[[1]][[2]][[1]][[1]][[2]][[2]] # <abundance>346.272257983685</abundance> 
xmltop[[1]][[2]][[1]][[1]][[3]][[1]] # <mz>605.519216627667</mz> 
xmltop[[1]][[2]][[1]][[1]][[3]][[2]] # <abundance>64.8701884746552</abundance> 
xmltop[[1]][[2]][[1]][[1]][[4]][[1]] # NULL 
xmltop[[1]][[2]][[1]][[1]][[4]][[2]] # NULL 

我不感兴趣,统计部,但我想创建一个数据帧中的STR输出会是李的东西科:

# > str(mydata) # returns a summary of the type/ format of each column 
# 'data.frame': n obs. of n variables: 
# $ compound : Factor w/ n levels 
# $ retention_time : 
# $ condition : Factor w/ 4 levels "D1","D3","D6","D9": 
# $ sample_name : Factor w/ 16 levels "ACU_S1_D1","ACU_S2_D1...: 
# $ isotope_mz : num 
# $ isotope_abundance : num 

我的最终目的是要能够提取每个isotope_mz的丰度为64个样本的每一个。事实上,知道条件并不重要,因为这可以从sample_name中确定。

N.B.我正在使用的xml文件是150 mb,并且具有> 4000个化合物x 64个样本,每个化合物都有1到4个同位素,我需要mz和丰度。除了这里要求的'R'方法之外,我还搜索并尝试了大量的xml转换器,但他们都没有能够破译这个xml文件的结构。

+2

你能不能给你需要的那种结果的例子吗?你也可以详细说明你的意思是“似乎没有工作”(它没有做什么?)和“进一步树”,举例。 – LarsH

+0

我会使用'XML :: xmlToList()'然后解析列表,因为你认为合适。此外,您在示例xml文件的底部缺少'<\compounds>' - 它不会在没有它的情况下加载。 – dayne

+0

谢谢你的问题。我已添加到原来的职位,包括我迄今为止的一些进展,并更好地描述了我的目标。 –

回答

1

像这样的东西应该工作:

library(XML) 
library(data.table) 

mylist <- xmlToList("isotope information.xml") 
mylist <- c(mylist, mylist, mylist) 

xtract <- function(x) { 
    data.table(compound_id = mylist[x]$compound$.attrs["identifier"], 
      sample_id = mylist[x]$compound$condition$sample$.attrs["name"], 
      mz = mylist[x]$compound$condition$sample$adduct$isotope[1], 
      abundance = mylist[x]$compound$condition$sample$adduct$isotope[2]) 
} 

rbindlist(lapply(seq_along(mylist), xtract)) 
#   compound_id  sample_id    mz   abundance 
# 1: 24.24_355.2087m/z ACU_S1_D1_MSonly 355.131459235488 0.115052197015018 
# 2: 24.24_355.2087m/z ACU_S1_D1_MSonly 355.131459235488 0.115052197015018 
# 3: 24.24_355.2087m/z ACU_S1_D1_MSonly 355.131459235488 0.115052197015018 
0

我个人比较喜欢xml2所以这里使用一个答案。我相信它可以得到改进,但它会给你一个长度等于化合物数量的列表,列表中的每个元素将是化合物标识符和mz和丰度列的data.frame。

library(xml2) 
x = read_xml(conn) # given in question 
#html_structure(x) # If you want to look at the structure 

output = list() 
# Initialize list and collect all compunds first 
a = xml_attrs(xml_find_all(x, "//compound")) 
# Iterate over compounds - I'm sure this could be done in an lapply... 
for(i in 1:length(a)){ 
    y = xml_child(x, i) 
    # Get the child to simplify the xpath to collect all in this one node 
    # Add a new element to the output list 
    output[[i]] = list(
    a[[1]][1], # Extract identifier (assumed you didn't want the retention time) and then a df of mz and abundance 
    data.frame(mz = xml_double(xml_find_all(y, "//isotope/mz")), abundance = xml_double(xml_find_all(x, "//isotope/abundance"))) 
       ) 
} 

OUTPUT:

> output 
[[1]] 
[[1]][[1]] 
     identifier 
"24.24_355.2087m/z" 

[[1]][[2]] 
     mz abundance 
1 355.1315 0.115052197 
2 355.7048 0.000000000 
... 
31 355.2422 1.253918178 
32 355.7048 0.000000000