首页 > 解决方案 > 使用 R 从大型 XML 中提取数据

问题描述

我有一个很大的 XML,由于内存不足,我无法在 R 中完全解析。我只想提取一些特定的列。我发现其他人问过类似的问题:

如何在 R 中读取大 (~20 GB) xml 文件? 使用 R 的 xmlEventParse 存储特定的 XML 节点值

我无法让它与我的数据一起工作,它运行,但没有返回数据。我确实尝试将建议的解决方案调整为我的 XML,但它仍然不起作用。可能是我缺乏XML知识。下面是我的 XML 数据的示例,cl, clssc, clp, clpssc, primclp列在哪里。如何仅提取cl而不clssc先解析整个文档?

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<abc:abc xmlns:abc="http://abc/abc" xsi:schemaLocation="http://abc/abc lala_20Q2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <chcp>
    <cl>2000000</cl>
    <clssc>10934</clssc>
    <clp>200000</clp>
    <clpssc>10934</clpssc>
    <primclp>Y</primclp>
  </chcp>
  <chcp>
    <cl>2000000</cl>
    <clssc>10934</clssc>
    <clp>200000</clp>
    <clpssc>10934</clpssc>
    <primclp>Y</primclp>
  </chcp>
  <chcp>
    <cl>2000000</cl>
    <clssc>10934</clssc>
    <clp>2000000</clp>
    <clpssc>10934</clpssc>
    <primclp>Y</primclp>
  </chcp>
</abc:abc>

标签: rxml

解决方案


在 Windows 机器上

这是一种方法,您可以使用 windows 命令的输出findstr来使用data.table::fread(). 它在将数据加载到 R之前使用 windows 版本的“grep”过滤数据。这样您就不会很快遇到内存问题。

xml的位置:e:/testdata.xml

进一步的解释在下面的数据评论中

library(data.table)
# Import output from windows findstr-command
#  assumes location of data is e:/testdata.xml
#  !! use \\ in path, else findstr does not undeerstand !!
DT <- data.table::fread(cmd = 'findstr "<clssc> <cl>" e:\\testdata.xml', 
                        sep = "\n", col.names = "line", header = FALSE )
#                    line
# 1:     <cl>2000000</cl>
# 2: <clssc>10934</clssc>
# 3:     <cl>2000000</cl>
# 4: <clssc>10934</clssc>
# 5:     <cl>2000000</cl>
# 6: <clssc>10934</clssc>

# Extract data from raw line
DT[, name  := gsub("^<(.+?)>.*$", "\\1", line)]
DT[, value := gsub("^.*>([0-9]+?)<.*$", "\\1", line)]
#                    line  name   value
# 1:     <cl>2000000</cl>    cl 2000000
# 2: <clssc>10934</clssc> clssc   10934
# 3:     <cl>2000000</cl>    cl 2000000
# 4: <clssc>10934</clssc> clssc   10934
# 5:     <cl>2000000</cl>    cl 2000000
# 6: <clssc>10934</clssc> clssc   10934

# Build some id's
DT[, id := rowid(name)]

# Cast to wide format
dcast(DT, id ~ name, value.var = "value")

#    id      cl clssc
# 1:  1 2000000 10934
# 2:  2 2000000 10934
# 3:  3 2000000 10934

在 unix 机器上
我无法测试,因为我只在这个位置使用 windows。
cmd='...'findstr-command(和正则表达式)中的部分替换为系统的 grep-command。


推荐阅读