【发布时间】:2018-04-20 03:29:59
【问题描述】:
基于上一个问题 (see here),我尝试通过 xmlEventParse 读取许多大型 xml 文件,同时保存节点变化的数据。使用此示例 xml:https://www.nlm.nih.gov/databases/dtd/medsamp2015.xml。
下面的代码使用 xpathSapply 提取必要的值和一系列 if 语句以将唯一值 (PMID) 与记录中的每个非唯一值 (LastName) 匹配的方式组合值 - 对于其中可能没有姓氏。目标是沿途编写一系列小的 csv(这里,在每 1000 个姓之后),以尽量减少使用的内存量。
在全尺寸数据集上运行时,代码成功地批量输出文件,但是内存中仍存储一些内容,一旦使用所有 RAM,最终会导致系统错误。我在代码运行时观察了任务管理器,并且可以看到 R 的内存随着程序的进行而增长。如果我在运行过程中停止程序然后清除 R 工作区,包括隐藏的项目,内存似乎仍在被 R 使用。直到我关闭 R 才再次释放内存。
自己运行几次,你会看到 R 的内存使用量即使在清除工作区后也会增长。
请帮忙!这个问题对于以这种方式读取大型 XML 文件的其他人来说似乎很常见(参见例如 cmets in this question)。
我的代码如下:
library(XML)
filename <- "~/Desktop/medsamp2015.xml"
tempdat <- data.frame(pmid=as.numeric(),
lname=character(),
stringsAsFactors=FALSE)
cnt <- 1
branchFunction <- function() {
func <- function(x, ...) {
v1 <- xpathSApply(x, path = "//PMID", xmlValue)
v2 <- xpathSApply(x, path = "//Author/LastName", xmlValue)
print(cbind(c(rep(v1,length(v2))), v2))
#below is where I store/write the temp data along the way
#but even without doing this, memory is used (even after clearing)
tempdat <<- rbind(tempdat,cbind(c(rep(v1,length(v2))), v2))
if (nrow(tempdat) > 1000){
outname <- paste0("~/Desktop/outfiles",cnt,".csv")
write.csv(tempdat, outname , row.names = F)
tempdat <<- data.frame(pmid=as.numeric(),
lname=character(),
stringsAsFactors=FALSE)
cnt <<- cnt+1
}
}
list(MedlineCitation = func)
}
myfunctions <- branchFunction()
#RUN
xmlEventParse(
file = filename,
handlers = NULL,
branches = myfunctions
)
【问题讨论】:
-
刚刚更新了代码,下载后应该可以运行:nlm.nih.gov/databases/dtd/medsamp2015.xml。内存问题仍然存在。
-
你在什么操作系统上运行? Windows、L*nux、Mac OSX?
-
也许你会使用类似 tempdat[i]
-
@Technophobe01 无论我是在 Windows 还是 Mac 上,我都会遇到这个问题,这让我认为这与 xmlEventParse 在内存中存储的东西有关,这些东西在没有 R 关闭的情况下是隐藏且不可擦除的
-
@km5041 您正在使用的库可能是用 c 或 c++ 编写的,它正在分配 R 会话控制之外的内存。因此,内存泄漏在 R 会话之外但会影响它。我解决这类问题的方法是跨 RScript 实例划分分析。打破工作。见:stackoverflow.com/questions/37264919/…
标签: r xml memory-management xml-parsing large-files