【发布时间】:2016-03-24 19:38:58
【问题描述】:
我有一个大约 45 GB 的非常大的 xml 文件,我正在尝试解析并创建一个数据框。 xml 的结构相当简单,如下所示。当类型为输入链接或左链接时,我想读取标签<event>下的属性。
<?xml version="1.0" encoding="utf-8"?>
<events version="1.0">
<event time="10800.0" type="actend" person="9982471" link="21225" actType="home" />
<event time="10800.0" type="departure" person="9982471" link="21225" legMode="car" />
<event time="10800.0" type="PersonEntersVehicle" person="9982471" vehicle="9982471" />
<event time="10800.0" type="actend" person="9656271" link="21066" actType="home" />
<event time="10833.0" type="entered link" person="4250461" link="24329" vehicle="4250461" />
<event time="10835.0" type="left link" person="1662941" link="29242" vehicle="1662941" />
<event time="10835.0" type="entered link" person="1662941" link="29239" vehicle="1662941" />
<event time="10836.0" type="left link" person="7651702" link="7359" vehicle="7651702" />
<event time="10836.0" type="entered link" person="7651702" link="7407" vehicle="7651702" />
<event time="10840.0" type="left link" person="8909152" link="5664" vehicle="8909152" />
</events>
我尝试了基于 DOM 的 xmlparse() 函数,但由于内存问题,它没有帮助。然后,我尝试了基于 SAX 的代码(如下所示),但耗时太长。例如,要读取 1% 的样本并从中创建一个数据框,我花了大约 5 个小时。所以,要对完整数据做同样的事情,我需要大约 20 天(假设它可以线性缩放)。你能帮我解决这个问题吗?以下是very small sample、1% sample、5% sample 和full data 的链接。
这是我使用的 SAX 代码。
library(XML)
branchFunction <- function() {
store <- new.env()
new_counter <- (function() {
i <- 0
function() {
i <<- i + 1
i
}
})()
func <- function(x, ...) {
ns <- getNodeSet(x,path = "//event[@type='left link' or @type='entered link']")
value <- lapply(ns, xmlAttrs)
store[[toString(new_counter())]] <- value
}
getStore <- function() { as.list( store ) }
list(event = func, getStore=getStore)
}
myfunctions <- branchFunction()
xmlEventParse(file = "percent1.gz", handlers = NULL, branches = myfunctions)
l <- myfunctions$getStore()
l <- unlist(l, recursive = FALSE)
df <- data.frame(matrix(unlist(l), nrow=length(l), byrow=T),stringsAsFactors=FALSE)
colnames(df) <- c("time", "type", "person", "link", "carid")
输出必须如下所示
> head(df)
time type person link carid
1 10934.0 entered link 9656271 16260 9656271
2 10935.0 left link 8909152 6014 8909152
3 10935.0 entered link 8909152 6034 8909152
4 10936.0 left link 1504062 25541 1504062
5 10936.0 entered link 1504062 25384 1504062
6 10936.0 left link 3055801 31464 3055801
【问题讨论】:
-
您在 SAX 方法中做错了什么,可能为每个 XPath 表达式重新处理整个文件。
-
有可能。但是,我不知道我的代码是否存在问题以及是什么问题。
-
在 XPath 中,双正斜杠
//搜索 xml 文档中的任何位置,并且通常被认为是一种昂贵的方法,因为每个命令都会扫描树结构中的所有底层后代。 -
@Parfait 我确实用
//和/对代码进行了基准测试,两者似乎在一个小样本上给出了相同的运行时间。虽然,你的观点很好。谢谢。