当值为多个或丢失时,从XML中恢复数据帧
这个问题类似于前面的问题,但我只想提取XML数据的一个子集,并希望包含缺少的/多个值 我从一个XML文件开始,希望基于它包含的一些数据(由XML元素的内容定义)在R中构建一个数据框架。用一个例子来解释是最容易的。在下面,我想挑选每个城市的地标信息(即使没有地标元素或有几个地标元素),忽略关于车站的信息当值为多个或丢失时,从XML中恢复数据帧,xml,r,xpath,import,dataframe,Xml,R,Xpath,Import,Dataframe,这个问题类似于前面的问题,但我只想提取XML数据的一个子集,并希望包含缺少的/多个值 我从一个XML文件开始,希望基于它包含的一些数据(由XML元素的内容定义)在R中构建一个数据框架。用一个例子来解释是最容易的。在下面,我想挑选每个城市的地标信息(即使没有地标元素或有几个地标元素),忽略关于车站的信息 <world> <city> <name>London</name> <buildings>
<world>
<city>
<name>London</name>
<buildings>
<building>
<type>landmark</type>
<bname>Tower Bridge</bname>
</building>
<building>
<type>station</type>
<bname>Waterloo</bname>
</building>
</buildings>
</city>
<city>
<name>New York</name>
<buildings>
<building>
<type>station</type>
<bname>Grand Central</bname>
</building>
</buildings>
</city>
<city>
<name>Paris</name>
<buildings>
<building>
<type>landmark</type>
<bname>Eiffel Tower</bname>
</building>
<building>
<type>landmark</type>
<bname>Louvre</bname>
</building>
</buildings>
</city>
</world>
我以为有一种方法可以使用XML库和xpathsaply
实现这一点,但我认为我失败了
如果不参考示例,也无法思考如何表达问题,因此请随意编辑以给出更具描述性的问题。您可以使用
xmlToList
,然后使用plyr
获取您可以使用的数据帧
require(XML)
require(plyr)
xD <- xmlParse(xData)
xL <- xmlToList(xD)
ldply(xL, data.frame)
> ldply(xL, data.frame)
.id name buildings.building.type buildings.building.bname
1 city London landmark Tower Bridge
2 city New York station Grand Central
3 city Paris landmark Eiffel Tower
buildings.building.type.1 buildings.building.bname.1
1 station Waterloo
2 <NA> <NA>
3 landmark Louvre
require(XML)
需要(plyr)
xD有一个解决方案xpathsaply
,但是在这里编写xpath有点复杂。
因此,这里我提出了一个解决方案,使用xmlToDataFrame
并使用一些正则表达式来获取建筑物
dd <- xmlToDataFrame(doc)
rr <- gsub('landmark',',',dd$buildings)
rr <- gsub('station.*','',rr)
builds <- lapply(strsplit(gsub('station.*','',rr),','),
function(x)x[nchar(x)>0])
dd$buildings <- builds
name buildings
1 London Tower Bridge
2 New York
3 Paris Eiffel Tower, Louvre
dd如果希望准确地再现问题中显示的所需输出,可以将XML转换为列表,然后提取所需信息:
xml_list <- xmlToList(xmlParse(xml_data))
xml\u list假设xml数据位于名为world.xml的文件中,将其读入并在城市中迭代,提取任何相关地标的城市名称和名称:
library(XML)
doc <- xmlParse("world.xml", useInternalNodes = TRUE)
do.call(rbind, xpathApply(doc, "/world/city", function(node) {
city <- xmlValue(node[["name"]])
xp <- "./buildings/building[./type/text()='landmark']/bname"
landmark <- xpathSApply(node, xp, xmlValue)
if (is.null(landmark)) landmark <- NA
data.frame(city, landmark, stringsAsFactors = FALSE)
}))
库(XML)
医生,谢谢。这个答案正是我想要的——很清楚如何使用xpath操作xml结构,并且不依赖xmlToDataFrame或xmlToList/ldply,这两种方法都无法处理我的真实数据,遗憾的是,这并不像我上面给出的world.xml示例那么简单:-)
xml_list <- lapply(xml_list, lapply, function(x) {
x[!sapply(x, function(y) any(y == "station"))]
})
xml_list <- lapply(xml_list, function(x) {
bldgs <- unlist(x$buildings)
bldgs <- bldgs[bldgs != "landmark"]
if(is.null(bldgs)) bldgs <- NA
data.frame(
"city" = x$name,
"landmark" = bldgs,
stringsAsFactors = FALSE)
})
xml_output <- do.call("rbind", xml_list)
xml_output
city landmark
city London Tower Bridge
city1 New York <NA>
city.1 Paris Eiffel Tower
city.2 Paris Louvre
library(XML)
doc <- xmlParse("world.xml", useInternalNodes = TRUE)
do.call(rbind, xpathApply(doc, "/world/city", function(node) {
city <- xmlValue(node[["name"]])
xp <- "./buildings/building[./type/text()='landmark']/bname"
landmark <- xpathSApply(node, xp, xmlValue)
if (is.null(landmark)) landmark <- NA
data.frame(city, landmark, stringsAsFactors = FALSE)
}))
city landmark
1 London Tower Bridge
2 New York <NA>
3 Paris Eiffel Tower
4 Paris Louvre