2015-09-19 133 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字段将是有问题的。