2015-09-19 139 views
1

我一直試圖進入R,並認爲最好的方法是想出一個我喜歡的項目,並深入其中。所以我想分析我的短信習慣。我設法我的文本導出爲以下格式的XML文件:使用R解析屬性的XML

<all> 
    <message date="1423813836987" number="+15555555" type="1" read="1" locked="1" seen="1">content of text</message> 
    <message date="1423813836987" number="+15555555" type="1" read="1" locked="1" seen="1">another content of text</message> 
</all> 

現在,我想要做的是提取屬性「日期」和「數量」和每封郵件的內容和創建一個數據框。我的最終目標是爲每個「數字」創建一個圖表,並查看我多久發短信的次數。

環顧四周後,我發現R的XML package。我可以提取郵件的內容,但無法從單個message標籤獲取屬性。一切,我發現關於屬性談到像嵌套的標籤:

<message> 
    <date>1423813836987</date> 
    <number>555-555</number> 
</message> 

會有人點我的方向是正確的?有沒有更好的方法來做這樣的事情?我到目前爲止是這樣的:

doc = xmlRoot(xmlTreeParse("~/Desktop/data.xml")) 
xml_data <- xmlToList(doc) 

但它使屬性看起來很時髦。

How the data looks like in RStudio

在此先感謝您。

回答

1

一個不錯的選擇使用xpathSApply

## create an xml Doc, replace the text by your file name 
xx <- htmlParse(' 
<all> 
    <message date="1423813836987" number="+15555555" type="1" read="1" locked="1" seen="1">content of text</message> 
    <message date="1423813836987" number="+15555555" type="1" read="1" locked="1" seen="1">another content of text</message> 
</all>',asText=T) 
## parsing 
data.frame(
    date=xpathSApply(xx,'//all/message',xmlGetAttr,'date'), 
    number=xpathSApply(xx,'//all/message',xmlGetAttr,'number'), 
    message=xpathSApply(xx,'//all/message',xmlValue)) 

##   date number     message 
## 1 1423813836987 +15555555   content of text 
## 2 1423813836987 +15555555 another content of text 
1

還是有點更簡潔使用Hadleyverse:

library(xml2) 
library(dplyr) 

# I modified the second record to ensure it was obvious the values carried through 

doc <- read_xml('<all> 
    <message date="1423813836987" number="+15555555" type="1" read="1" locked="1" seen="1">content of text</message> 
    <message date="1010191919191" number="+22828282" type="2" read="3" locked="0" seen="1">another content of text</message> 
</all>') 

msgs <- xml_find_all(doc, "//message") 

bind_cols(bind_rows(lapply(xml_attrs(msgs), as.list)), 
      data_frame(message=xml_text(msgs))) 

## Source: local data frame [2 x 7] 
## 
##   date number type read locked seen     message 
##   (chr)  (chr) (chr) (chr) (chr) (chr)     (chr) 
## 1 1423813836987 +15555555  1  1  1  1   content of text 
## 2 1010191919191 +22828282  2  3  0  1 another content of text 

如果你不想使用dplyr

cbind.data.frame(do.call(rbind, xml_attrs(msgs)), 
       messages=xml_text(msgs), 
       stringsAsFactors=FALSE) 

##   date number type read locked seen    messages 
## 1 1423813836987 +15555555 1 1  1 1   content of text 
## 2 1010191919191 +22828282 2 3  0 1 another content of text 

使用XML包也很容易:

bind_cols(bind_rows(lapply(xpathApply(doc, "//message", xmlAttrs), as.list)), 
      data_frame(message=xpathSApply(doc, "//message", xmlValue))) 

泡沫。沖洗。重複基本示例,如果你想堅持基地。

如果有不需要的列只是使用數據幀列切片來擺脫它們。

如果你想自動類型轉換,你可以看看type.convert,但如果你需要+number字段將是有問題的。