2009-12-02 21 views
4

讓我們說,我有這樣的XML文件:如何使用xml數據進行矢量化?

<?xml version="1.0" encoding="UTF-8" ?> 
<TimeSeries> 
    <timeZone>1.0</timeZone> 
    <series> 
    <header/> 
    <event date="2009-09-30" time="10:00:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:15:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:30:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:45:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="11:00:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="11:15:00" value="0.0" flag="2"></event> 
    </series> 
    <series> 
    <header/> 
    <event date="2009-09-30" time="08:00:00" value="1.0" flag="2"></event> 
    <event date="2009-09-30" time="08:15:00" value="2.6" flag="2"></event> 
    <event date="2009-09-30" time="09:00:00" value="6.3" flag="2"></event> 
    <event date="2009-09-30" time="09:15:00" value="4.4" flag="2"></event> 
    <event date="2009-09-30" time="09:30:00" value="3.9" flag="2"></event> 
    <event date="2009-09-30" time="09:45:00" value="2.0" flag="2"></event> 
    <event date="2009-09-30" time="10:00:00" value="1.7" flag="2"></event> 
    <event date="2009-09-30" time="10:15:00" value="2.3" flag="2"></event> 
    <event date="2009-09-30" time="10:30:00" value="2.0" flag="2"></event> 
    </series> 
    <series> 
    <header/> 
    <event date="2009-09-30" time="10:00:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:15:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:30:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="10:45:00" value="0.0" flag="2"></event> 
    <event date="2009-09-30" time="11:00:00" value="0.0" flag="2"></event> 
    </series> 
</TimeSeries> 

,讓我們說我想要做的事與它的一系列元素,而且我想付諸實踐的意見「向量化向量化」 ......我導入XML庫並執行以下操作:

R> library("XML") 
R> doc <- xmlTreeParse('/home/mario/Desktop/sample.xml') 
R> TimeSeriesNode <- xmlRoot(doc) 
R> seriesNodes <- xmlElementsByTagName(TimeSeriesNode, "series") 
R> length(seriesNodes) 
[1] 3 
R> (function(x){length(xmlElementsByTagName(x[['series']], 'event'))} 
+)(seriesNodes) 
[1] 6 
R> 

,我不明白爲什麼我應該只得到應用功能的第一個元素的結果是:我所預料的三個值,就像seriesNodes的長度,像這樣:

R> mapply(length, seriesNodes) 
series series series 
    7  10  6 

哎呀!我已經想出了答案:「用mapply」:

R> mapply(function(x){length(xmlElementsByTagName(x, 'event'))}, seriesNodes) 
series series series 
    6  9  5 

但後來我看到下面的問題:R-魔族告訴我,我是‘循環隱藏’,而不是‘矢量化’!我可以避免循環嗎? ...

回答

3

您也可以使用xpathApplyxpathSApply - 這些函數使用XPath規範提取節點集,然後每個集執行一個函數。這兩個功能都由XML包提供。爲了使用這些功能,XML文檔必須使用xmlInternalTreeParse或解析與xmlTreeParseuseInternalNodes選項設置爲true:

require(XML) 

countEvents <- function(series){ 

    events <- xmlElementsByTagName(series, 'event') 
    return(length(events)) 

} 

doc <- xmlTreeParse("sample.xml", useInternalNodes = T) 

xpathSApply(doc, '/TimeSeries/series', countEvents) 
[1] 6 9 5 

我不知道這是否是任何「更快」,但代碼對於瞭解XPath語法以及函數如何操作的人來說,它絕對更清晰並且非常明確。

+0

來自xpathSApply的幫助也特別有啓發性(我仍然使用XML包!)。 – mariotomo 2009-12-03 07:51:44

3

由於seriesNodes是節點列表,因此沒有簡單的方法可以避免隱式循環。簡單的操作如獲得長度不是計算密集型的,所以我不會失去任何睡眠而不能進行矢量化。

請注意,您可以使用sapply(seriesNodes, length)而不是mapply,因爲length函數只有一個參數。

做「事情的正確方式」是使用(s|m)apply調用來提取有用位數據的向量,然後以通常的方式分析這些向量。

最後,如果您真的非常想要引導計數事件,請使用names(unlist(seriesNodes)),然後在"series.name"的每次出現之間計算出"series.children.event.name"的發生次數。這無疑是更醜陋的,並且可能比sapply電話慢。

相關問題