将XML更高的节点属性、节点值和文件名获取到R data.frame
我已经和它斗争了很长一段时间,无法让它工作,所以我在这里发布。我不是一个高级的R用户,但我正在学习并慢慢前进。我还没有从Stackoverflow中找到一个可以适应这种情况的示例,这些示例似乎具有不同的结构,不需要循环每个节点的每个更高级别属性。或者这就是我现在理解差异的原因。问题与类似,但文件结构不同。现在我基本上用了 假设我有大量小XML文件,其结构如下所示。它们有file1.xml、file2.xml等名称。因此,file1.xml应该是:将XML更高的节点属性、节点值和文件名获取到R data.frame,xml,r,dataframe,Xml,R,Dataframe,我已经和它斗争了很长一段时间,无法让它工作,所以我在这里发布。我不是一个高级的R用户,但我正在学习并慢慢前进。我还没有从Stackoverflow中找到一个可以适应这种情况的示例,这些示例似乎具有不同的结构,不需要循环每个节点的每个更高级别属性。或者这就是我现在理解差异的原因。问题与类似,但文件结构不同。现在我基本上用了 假设我有大量小XML文件,其结构如下所示。它们有file1.xml、file2.xml等名称。因此,file1.xml应该是: <NODE> <SUBNODE
<NODE>
<SUBNODE TYPE="WORDS" SPEAKER="person1">
<WORD>word1</WORD>
<WORD>word2</WORD>
<WORD>word3</WORD>
</SUBNODE>
<SUBNODE TYPE="WORDS" SPEAKER="person2">
<WORD>word4</WORD>
<WORD>word5</WORD>
<WORD>word6</WORD>
</SUBNODE>
</NODE>
<NODE>
<SUBNODE TYPE="WORDS" SPEAKER="person3">
<WORD>word7</WORD>
<WORD>word8</WORD>
<WORD>word9</WORD>
</SUBNODE>
<SUBNODE TYPE="WORDS" SPEAKER="person4">
<WORD>word10</WORD>
<WORD>word11</WORD>
<WORD>word12</WORD>
</SUBNODE>
</NODE>
我可以使用以下命令将所有单词的列表放入一个数据框中:
library(XML)
library(plyr)
xmlfiles <- list.files(pattern = "*.xml")
dat <- ldply(seq(xmlfiles), function(i){
doc <- xmlTreeParse(xmlfiles[i], useInternal = TRUE)
Word <- xpathSApply(doc, "//SUBNODE[@TYPE='WORDS']/WORD", xmlValue)
return(data.frame(Word))
})
然后,我也经常会出现如下错误:
"Error in UseMethod("xmlValue") :
no applicable method for 'xmlValue' applied to an object of class "c('XMLInternalDocument', 'XMLAbstractDocument')"
或者我得到了一个错误,它们的长度不同,它们当然是,因为说话者比单词少。我尝试过很多东西,但我在这里只发布了我“最成功”的方法。我知道我需要一个函数,将上面节点中的每个单词与speaker属性进行某种程度的匹配,只是将它们提取到它们自己的列表中没有帮助,我想现在很幸运,在这个示例中,说话人和单词的数量是匹配的,所以它们像上面的数据框一样放在一起
然后我仍然需要将文件名放在一列中,因为它们包含一段我在XML文件本身中没有的信息。无论如何,这是我问题中最不重要的方面。我处理的实际文件要复杂得多,这就是为什么我在文件中有一些不必要的结构,比如子节点类型,等等
谢谢你的帮助 一种可能是获取所有相关值(
xml
是我认为您的doc
)
找到扬声器并将所有内容转换为简单的字符向量
isSpeaker = sapply(x, is, "XMLAttributeValue")
x[!isSpeaker] = sapply(x[!isSpeaker], xmlValue)
x = unlist(x, use.names=FALSE)
然后咀嚼结果
r = rle(isSpeaker)
data.frame(Speaker=rep(x[isSpeaker], r$length[!r$value]), Word=x[!isSpeaker])
(我不认为这对没有文字的演讲者来说是可靠的,但那会是什么样的演讲者?一种可能是获取所有相关值(
xml
是我认为你的doc
)
找到扬声器并将所有内容转换为简单的字符向量
isSpeaker = sapply(x, is, "XMLAttributeValue")
x[!isSpeaker] = sapply(x[!isSpeaker], xmlValue)
x = unlist(x, use.names=FALSE)
然后咀嚼结果
r = rle(isSpeaker)
data.frame(Speaker=rep(x[isSpeaker], r$length[!r$value]), Word=x[!isSpeaker])
(我不认为这对没有文字的演讲者来说是可靠的,但那会是什么样的演讲者?我可能会尝试循环文件并解析getNodeSet。我不经常使用ldply,但是您可以用它来替换循环
xmlfiles <- list.files(pattern = "*.xml")
n <- length(xmlfiles)
dat <- vector("list", n)
for(i in 1:n){
doc <- xmlParse(xmlfiles[i])
nodes <- getNodeSet(doc, "//SUBNODE")
x<- lapply(nodes, function(x){ data.frame(
Filename = xmlfiles[i],
Speaker= xpathSApply(x, "." , xmlGetAttr, "SPEAKER"),
Word= xpathSApply(x, ".//WORD" , xmlValue) )})
dat[[i]] <- do.call("rbind", x)
}
do.call("rbind", dat)
xmlfiles我可能会尝试遍历这些文件并解析getNodeSet。我不经常使用ldply,但是您可以用它来替换循环
xmlfiles <- list.files(pattern = "*.xml")
n <- length(xmlfiles)
dat <- vector("list", n)
for(i in 1:n){
doc <- xmlParse(xmlfiles[i])
nodes <- getNodeSet(doc, "//SUBNODE")
x<- lapply(nodes, function(x){ data.frame(
Filename = xmlfiles[i],
Speaker= xpathSApply(x, "." , xmlGetAttr, "SPEAKER"),
Word= xpathSApply(x, ".//WORD" , xmlValue) )})
dat[[i]] <- do.call("rbind", x)
}
do.call("rbind", dat)
xmlfiles这也很有效!非常感谢。由于某些原因,我在“do.call(“rbind”,dat”)“do.call中的错误(“rbind”,“dat”):第二个参数必须是一个列表”你对为什么会发生这种情况有什么建议吗?我应该检查一下这个do.call(“rbind”)-东西是什么。它对do.call(“rbind”,dat)很有吸引力),并且很容易将其应用到我的实际数据中。谢谢!很抱歉出现了这个错误-它在上面被修复了这也很好!谢谢!出于某种原因,我在“do.call(“rbind”,dat”)“do.call中的错误(“rbind”,“dat”):第二个参数必须是一个列表”你有什么建议为什么会发生这种情况吗?我应该检查一下这是怎么回事。它与do.call(“rbind”,dat)的工作原理类似,很容易将其应用到我的真实数据中。谢谢对不起,上面的错误已经纠正了
xmlfiles <- list.files(pattern = "*.xml")
n <- length(xmlfiles)
dat <- vector("list", n)
for(i in 1:n){
doc <- xmlParse(xmlfiles[i])
nodes <- getNodeSet(doc, "//SUBNODE")
x<- lapply(nodes, function(x){ data.frame(
Filename = xmlfiles[i],
Speaker= xpathSApply(x, "." , xmlGetAttr, "SPEAKER"),
Word= xpathSApply(x, ".//WORD" , xmlValue) )})
dat[[i]] <- do.call("rbind", x)
}
do.call("rbind", dat)