【发布时间】:2014-08-25 16:08:34
【问题描述】:
我正在尝试解析 XML 文件。它的简化版本如下所示:
x <- '<grandparent><parent><child1>ABC123</child1><child2>1381956044</child2></parent><parent><child2>1397527137</child2></parent><parent><child3>4675</child3></parent><parent><child1>DEF456</child1><child3>3735</child3></parent><parent><child1/><child3>3735</child3></parent></grandparent>'
library(XML)
xmlRoot(xmlTreeParse(x))
## <grandparent>
## <parent>
## <child1>ABC123</child1>
## <child2>1381956044</child2>
## </parent>
## <parent>
## <child2>1397527137</child2>
## </parent>
## <parent>
## <child3>4675</child3>
## </parent>
## <parent>
## <child1>DEF456</child1>
## <child3>3735</child3>
## </parent>
## <parent>
## <child1/>
## <child3>3735</child3>
## </parent>
## </grandparent>
我想将 XML 转换为如下所示的 data.frame / data.table:
parent <- data.frame(child1=c("ABC123",NA,NA,"DEF456",NA), child2=c(1381956044, 1397527137, rep(NA, 3)), child3=c(rep(NA, 2), 4675, 3735, 3735))
parent
## child1 child2 child3
## 1 ABC123 1381956044 NA
## 2 <NA> 1397527137 NA
## 3 <NA> NA 4675
## 4 DEF456 NA 3735
## 5 <NA> NA 3735
如果每个父节点总是包含所有可能的元素(“child1”、“child2”、“child3”等),我可以使用xmlToList 和unlist 将其展平,然后使用dcast把它放到一张桌子上。但是 XML 经常缺少子元素。这是一个输出不正确的尝试:
library(data.table)
## Flatten:
dt <- as.data.table(unlist(xmlToList(x)), keep.rownames=T)
setnames(dt, c("column", "value"))
## Add row numbers, but they're incorrect due to missing XML elements:
dt[, row:=.SD[,.I], by=column][]
column value row
1: parent.child1 ABC123 1
2: parent.child2 1381956044 1
3: parent.child2 1397527137 2
4: parent.child3 4675 1
5: parent.child1 DEF456 2
6: parent.child3 3735 2
7: parent.child3 3735 3
## Reshape from long to wide, but some value are in the wrong row:
dcast.data.table(dt, row~column, value.var="value", fill=NA)
## row parent.child1 parent.child2 parent.child3
## 1: 1 ABC123 1381956044 4675
## 2: 2 DEF456 1397527137 3735
## 3: 3 NA NA 3735
我不会提前知道子元素的名称,或者祖父母的孩子的唯一元素名称的数量,所以答案应该是灵活的。
更新示例
实际的 XML 文件有多层嵌套,使用 xmlToDataFrame 时出现错误。这是一个更新的(但仍然是简化的)版本:
x2 <- '<grandparent><grandparentInfo junk="TRUE"><grandparent1>foo</grandparent1><grandparent1>bar</grandparent1></grandparentInfo><parent><child1>ABC123</child1><child2>1381956044</child2></parent><parent><child2>1397527137</child2></parent><parent><child3>4675</child3></parent><parent><child1>DEF456</child1><child3>3735</child3></parent><parent><child1/><child3>3735</child3></parent></grandparent>'
xmlToDataFrame(x2)
## Error in `[<-.data.frame`(`*tmp*`, i, names(nodes[[i]]), value = c("foo", :
## duplicate subscripts for columns
【问题讨论】:
-
xmlToDataFrame不是你要找的功能吗? -
@sgibb - 我认为这是正确的。我通过
xmlToDataFrame(x)得到了 OP 想要的结果 -
感谢@sgibb 和@RichardScriven。请参阅更新后的示例,
x2。
标签: xml r dataframe data.table reshape