当前位置 : 主页 > 网页制作 > xml >

将许多XML文件合并到R中的一个数据框中

来源:互联网 收集:自由互联 发布时间:2021-06-13
我有很多 XML文件(大约100,000个),它们都如下所示.每个文件有大约100个点节点.我只展示其中五个用于说明. ?xml version="1.0" encoding="UTF-8"?-car id="id1"point time="1272686841" lon="-122.40648" lat="37.7977
我有很多 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,000×100 = 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循环(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'

有没有办法加快这个过程?

考虑一个lapply()解决方案,它可以加快文件迭代.并且因为所有数据都驻留在属性中,所以您可以在一次调用中使用XML的xPathSApply().

library(XML)

setwd("C:\\Users\\MyName\\Desktop\\XMLTest")
all.files <- list.files(pattern="\\.xml", path=getwd(), full.names=TRUE)

dfList <- lapply(all.files, function(x){
  xml <- xmlParse(x)
  pointAttribs <- xpathSApply(doc=xml, path="//point",  xmlAttrs)
  # TRANSPOSE XPATH LIST TO DF 
  df <- data.frame(t(pointAttribs))
  # CONVERT TO NUMERIC
  df[c('time', 'lon', 'lat')] <- sapply(df[c('time', 'lon', 'lat')], 
                                        function(x) as.numeric(as.character(x)))
  return(df)
})

df <- do.call(rbind, dfList)
df
#          time       lon      lat status unit
# 1  1272686841 -122.4065 37.79778      E  id1
# 2  1272686781 -122.4054 37.79714      M  id1
# 3  1272686722 -122.4071 37.79774      M  id1
# 4  1272686661 -122.4070 37.79760      M  id1
# 5  1272686619 -122.4062 37.79698      E  id1
...
网友评论