对于每个节点,计算在R中使用XML包的子节点的数量

问题描述:

我对XML解析相当陌生,并试图解析一些篮球NBA sportVU数据。我有一个看起来如此(在总结格式)的XML文件:对于每个节点,计算在R中使用XML包的子节点的数量

<quarter number="1"> 
    <possession team-id="30" points="3"/> 
    <possession team-id="23" points="1"/> 
    <possession team-id="30" points="2"/> 
</quarter> 
<quarter number="2"> 
    <possession team-id="23" points="3"/> 
    <possession team-id="30" points="2"/> 
</quarter> 
<quarter number="3"> 
    <possession team-id="30" points="1"/> 
    <possession team-id="30" points="1"/> 
    <possession team-id="30" points="1"/> 
    <possession team-id="23" points="2"/> 
</quarter> 
<quarter number="4"> 
    <possession team-id="23" points="2"/> 
</quarter> 

我创建了具有团队ID为1列中的数据帧,并点作为另一列的数量,因为这样的:

library(XML) 
data = xmlParse("myXMLfile.XML") 

my_df <- data.frame(
    team.id = sapply(data["//quarter/possession/@team-id"], as, "integer"), 
    points = sapply(data["//quarter/possession/@points"], as, "integer") 
) 

my_df 
    team.id points 
1  30  3 
2  23  1 
3  30  2 
4  23  3 
5  30  2 
6  30  1 
7  30  1 
8  30  1 
9  23  2 
10  23  2 

我想第3列添加到这个标记季度,这将更新数据框,看起来像这样:

my_new_df 
    team.id points quarter 
1  30  3  1 
2  23  1  1  
3  30  2  1 
4  23  3  2 
5  30  2  2 
6  30  1  3 
7  30  1  3 
8  30  1  3 
9  23  2  3 
10  23  2  4 

我想,能够做到这一点最简单的方法,是抓住了向量中的唯一四分之一数字,然后通过每个四分之一节点下面的子节点数重复该向量。有人知道我能做到吗?我对一般不同的方法开放,不涉及XML包(例如,如果有xml2解决方案)。

谢谢!

看起来像这样会工作,从原始文件data(我称之为doc)开始。首先需要一个辅助函数来将期望的信息转换为所需的形式。现在

helper <- function(x) { 
    as.data.frame.list(c(xmlAttrs(x), quarter = unname(xmlAttrs(xmlParent(x))))) 
} 

我们可以lapply()运行我们的跨节点辅助函数,并把结果列表到数据帧与rbind()

do.call(rbind, lapply(doc["//quarter/*"], helper)) 
# team.id points quarter 
# 1  30  3  1 
# 2  23  1  1 
# 3  30  2  1 
# 4  23  3  2 
# 5  30  2  2 
# 6  30  1  3 
# 7  30  1  3 
# 8  30  1  3 
# 9  23  2  3 
# 10  23  2  4 

数据:

library(XML) 
doc <- htmlParse('<quarter number="1"> 
    <possession team-id="30" points="3"/> 
    <possession team-id="23" points="1"/> 
    <possession team-id="30" points="2"/> 
</quarter> 
<quarter number="2"> 
    <possession team-id="23" points="3"/> 
    <possession team-id="30" points="2"/> 
</quarter> 
<quarter number="3"> 
    <possession team-id="30" points="1"/> 
    <possession team-id="30" points="1"/> 
    <possession team-id="30" points="1"/> 
    <possession team-id="23" points="2"/> 
</quarter> 
<quarter number="4"> 
    <possession team-id="23" points="2"/> 
</quarter>') 
+0

Thanks Rich。它看起来像使用xpathApply是一种使用XML包解析XML文档的强大方法。我看起来他们用了很多。 – Canovice

+0

@Canovice - 它有它的起伏:) –

像这样的事情似乎工作,虽然不是在我看来最大的解决方案。它使用XML :: xmlChildren函数:

zed = possessions["//quarter"] 
unlist(lapply(zed, FUN = function(x) length(XML::xmlChildren(x)))) 

3 2 4 1