从R中的大型XML文件中提取数据的最有效方法

从R中的大型XML文件中提取数据的最有效方法,r,xml,xml2,R,Xml,Xml2,我有几个大的(~10GB,每周都在增长),我需要将它们从XML转换为R中的数据帧进行分析。XML的结构如下所示(具有多个记录和每个记录多几个字段元素): 我曾经尝试过XML2(内存问题)、XML(内存问题以及标准DOM解析),还打算尝试使用XMLSchema,但没有成功。如果文件被拆分,XML和XML2都可以工作 如果您能提供任何关于提高效率的指导,我将不胜感激,因为我正在处理的文件每周都在变大。我在Linux机器上使用R。 < P>当内存是一个挑战时,考虑硬盘。具体地说,考虑通过在代码< >代

我有几个大的(~10GB,每周都在增长),我需要将它们从XML转换为R中的数据帧进行分析。XML的结构如下所示(具有多个记录和每个记录多几个字段元素):

我曾经尝试过XML2(内存问题)、XML(内存问题以及标准DOM解析),还打算尝试使用XMLSchema,但没有成功。如果文件被拆分,XML和XML2都可以工作


如果您能提供任何关于提高效率的指导,我将不胜感激,因为我正在处理的文件每周都在变大。我在Linux机器上使用R。

< P>当内存是一个挑战时,考虑硬盘。具体地说,考虑通过在代码< >代码> XMLVTEN PARSE> <代码>运行:

,通过迭代的附加调用建立一个大的CSV版本的迭代解析的XML数据。
#用空行初始化空CSV

csv最后,我发现最快的方法是:

  • 使用XML2将XML文件拆分为更小的块。我正在使用的服务器上有>100GB的RAM,因此可以使用带有6个工作线程的
    foreach
    并行化此过程,但里程数取决于可用RAM的数量
  • 分割文件的函数返回带有分割文件位置的data.frame
  • foreach
    循环中处理较小的XML文件-这一次可以使用所有核心,因此我使用了12个工作人员。处理使用XML2,因为我发现这是最快的方法。最初提取的数据是长格式的,但我随后在循环中转换为宽格式
  • 循环将不同的数据帧绑定并输出到一个大数据帧中。最后一步是使用
    fwrite
    保存csv文件。这似乎是最有效的方法
  • 使用这种方法,我可以在6.5分钟内处理一个2.6GB的XML文件


    我最终会添加代码,但它非常具体,因此需要进行一些概括。

    您在这里看到答案中的更新了吗@ibilgen谢谢是的-我也尝试过类似的方法,但由于我的数据集非常大,使用XML2进行解析可能需要几个小时,因此我试图找到最有效的方法。我还没有弄清楚如何使用XSLT,这在对该问题的另一个回答中提到。请参阅。公认的解决方案使用
    xmlEventParse
    @Parfait使用分支的方法似乎也能工作,并且看起来比使用处理程序稍微快一点。我会继续努力并发布代码,希望对其他人有用。谢谢-我一直在尝试类似的方法,但没有成功。您的示例运行得很好,但编写csv似乎需要时间。它在一分钟内只管理了大约100条记录。我试图转换您的代码以生成一个数据帧,该数据帧速度稍快,但仍然相当慢(3.5分钟内有10000条记录,我还有150万条记录要处理)。我有一种感觉,我必须接受,任何少于一个小时的处理都足够好!RAM通常比磁盘读取速度快。但要避免在内存中增加大数据帧。此解决方案试图避免大量的、不断增长的RAM占用空间。重新启动计算机,避免运行其他应用程序和IDE,如RStudio,并在命令行中使用
    RScript
    运行此操作。不要将XML或CSV存储到外部或网络驱动器,而是存储到硬盘驱动器。您是如何使用XML2拆分XML文件的?我面临着同样的问题,但还没有找到令人满意的解决办法。
    <recordGroup>
      <records>
        <record>
          <recordId>123442</recordId>
          <reportingCountry>PT</reportingCountry>
          <date>2020-02-20</date>
          <field>
            <fieldName>Gender</fieldName>
            <fieldValue>F</fieldValue>
          </field>
          <field>
            <fieldName>Age</fieldName>
            <fieldValue>57</fieldValue>
          </field>
          <field>
            <fieldName>ClinicalSymptoms</fieldName>
            <fieldValue>COUGH</fieldValue>
            <fieldValue>FEVER</fieldValue>
            <fieldValue>O</fieldValue>
            <fieldValue>RUNOS</fieldValue>
            <fieldValue>SBREATH</fieldValue>
          </field>
        </record>
      </records>
    </recordGroup>
    
    value_df <- data.frame(recordId = as.character(), vardf = as.character(), value = as.character())
    nvar <- 0
    
    xmlEventParse(xmlDoc_clean,
                  list(
                    startElement = function (name, attrs) {
                      tagName <<- name
                    },
                    text = function (x) {
                      if (nchar(x) > 0) {
                        if (tagName == "recordId") {
                          rec <<- x
                        } else
                        if (tagName == "fieldName") {
                          var_f <<- x
                        } else {
                          if (tagName == 'fieldValue') {
                            v <- x
                             nvar <<- nvar + 1
                           value_df[nvar, 1:3] <<- c(rec, var_f, v)
                          }
                        }
                      }
                    },
                    endElement = function (name) {
                      if (name == 'record') {
                        print(nvar)
                      }
                    }
                  ))
    
    id,tag,text
    1,"recordId","123442"
    1,"reportingCountry","PT"
    1,"date","2020-02-20"
    1,"fieldName","Gender"
    1,"fieldValue","F"
    1,"fieldName","Age"
    1,"fieldValue","57"
    1,"fieldName","ClinicalSymptoms"
    1,"fieldValue","COUGH"
    1,"fieldValue","FEVER"
    1,"fieldValue","O"
    1,"fieldValue","RUNOS"
    1,"fieldValue","SBREATH"