【发布时间】:2021-03-07 01:47:18
【问题描述】:
我有许多 XML 文件(大约 100,000 个),它们都如下所示。每个文件有大约 100 个点节点。为了说明,我只展示了其中的五个。
<?xml version="1.0" encoding="UTF-8"?>
-<car id="id1">
<point time="1272686841" lon="-122.40648" lat="37.79778" status="E" unit="id1"/>
<point time="1272686781" lon="-122.40544" lat="37.79714" status="M" unit="id1"/>
<point time="1272686722" lon="-122.40714" lat="37.79774" status="M" unit="id1"/>
<point time="1272686661" lon="-122.40704" lat="37.7976" status="M" unit="id1"/>
<point time="1272686619" lon="-122.40616" lat="37.79698" status="E" unit="id1"/>
</car>
我想将所有这些 XML 文件合并到 R 中的一个大数据框(大约 100,000x100=10,000,000 行),其中包含五列(时间、经度、纬度、单位、状态)。所有文件都有相同的五个变量,但它们的顺序可能不同。
以下是我的代码。我首先创建了五个向量来保存这五个变量。然后我去每个文件,一个一个地读取条目。
setwd("C:\\Users\\MyName\\Desktop\\XMLTest")
all.files <- list.files()
n <- 2000000
all.lon <- rep(NA, n)
all.lat <- rep(NA, n)
all.time <- rep(NA, n)
all.status <- rep(NA, n)
all.unit <- rep(NA, n)
i <- 1
for (cur.file in all.files) {
if (tolower(file_ext(cur.file)) == "xml") {
xmlfile <- xmlTreeParse(cur.file)
xmltop <- xmlRoot(xmlfile)
for (j in 1:length(xmltop)) {
cur.node <- xmltop[[j]]
cur.lon <- as.numeric(xmlGetAttr(cur.node, "lon"))
cur.lat <- as.numeric(xmlGetAttr(cur.node, "lat"))
cur.time <- as.numeric(xmlGetAttr(cur.node, "time"))
cur.unit <- xmlGetAttr(cur.node, "unit")
cur.status <- xmlGetAttr(cur.node, "status")
all.lon[i] <- cur.lon
all.lat[i] <- cur.lat
all.time[i] <- cur.time
all.status[i] <- cur.status
all.unit[i] <- cur.unit
i <- i + 1
}
}
}
我是 XML 新手,所以这是我现在能做的最好的事情。问题是它非常慢。一个原因是文件太多。另一个原因是 for 循环 for (j in 1:length(xmltop)) 来读取条目。我试过xmlToDataFrame,但它不起作用。
> xmlToDataFrame(cur.file)
Error in matrix(vals, length(nfields), byrow = TRUE) :
'data' must be of a vector type, was 'NULL'
有什么方法可以加快这个过程吗?
【问题讨论】:
-
如果你所有的 XML 文件看起来都一样,你可以试试
readLines,我认为它非常快,但会返回原始字符串。然后,您可以使用lapply的函数从字符串中提取相关值。 -
使用 xml2 包,只需几条语句就可以处理整个文件。请参阅 xml2 包中的 xml_nodes 和 xml_attr 函数。这将消除内部循环以提高性能。
-
@Dave2e 我会看看
xml2包。谢谢。