对于每个节点,计算在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>')
答
像这样的事情似乎工作,虽然不是在我看来最大的解决方案。它使用XML :: xmlChildren函数:
zed = possessions["//quarter"]
unlist(lapply(zed, FUN = function(x) length(XML::xmlChildren(x))))
3 2 4 1
Thanks Rich。它看起来像使用xpathApply是一种使用XML包解析XML文档的强大方法。我看起来他们用了很多。 – Canovice
@Canovice - 它有它的起伏:) –