将大型嵌套xml放入R Dataframe 的更快方法

qaxu7uf2  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(113)

我有一个XML文件,它的嵌套与我见过的其他示例不同。下面是它采用的格式。我对np节点中的数据感兴趣,但我还希望每行中包含组和ID信息。
下面我有一个可行的解决方案,但是实际的文件非常大,有数千个节点。尽管它可以在下面的示例代码上工作,但是这个解决方案在这个大文件上运行需要花费很多时间。
我的问题是-有没有更快的方法来获得我想要的 Dataframe ?

<File>
  <Time>
    <date>20220301</date>
    <Name>1</Name>
<folder>
      <group>800</group>
      <ID>ESK</ID>
      <Type>S</Type>
      <Customer>1</Customer>
      <currency>USD</currency>
      <Port>
        <ec>X</ec>
        <np>
          <A>FIRST</A>
          <B>ES</B>
          <C>GOR</C>
          <D>2021</D>
          <E>-1000</E>
        </np>
        <np>
          <A>TEST</A>
          <B>ES</B>
          <C>RUN</C>
          <D>202303</D>
          <E>202303</E>
          <F>C</F>
          <G>3200</G>
          <H>32</H>
        </np>
      </Port>
</folder>
<folder>
      <group>900</group>
      <ID>ABC</ID>
      <Type>D</Type>
      <Customer>1</Customer>
      <currency>USD</currency>
      <Port>
        <ec>X</ec>
        <np>
          <A>CAT</A>
          <B>ES</B>
          <C>GO</C>
          <D>202303</D>
          <E>-500</E>
        </np>
       </Port>
</folder>
</Time>
</File>

这是我目前的解决方案,它可以处理小的xml文件,但是对于大的xml格式的文件来说,它太慢了,需要几个小时才能运行。

URL <- 'H:/testSO.xml'
doc <- read_xml(URL)

df <-
  xml_find_all(doc, ".//np") %>%
  map_df( function(x) {
    set_names( c(  
      xml_find_all( x, "./ancestor::folder/group") %>% xml_text(),
      xml_find_all( x, "./ancestor::folder/ID") %>% xml_text(),
      xml_find_all( x, ".//A") %>% xml_text(),
      xml_find_all( x, ".//B") %>% xml_text(),
      xml_find_all( x, ".//C") %>% xml_text(),
      xml_find_all( x, ".//D") %>% xml_text(),
      xml_find_all( x, ".//E") %>% xml_text()), 
      #set the column names
      c( "group","id", "A", "B", "C","D","E") ) %>% 
      as.list() %>% #make list
      flatten_df() 
  }) %>%
  type_convert() 

head(df)

谢谢!

ttcibm8c

ttcibm8c1#

您可以利用 xml2 库的矢量化功能,避免map_df循环,这将显著提高速度。
这个例程找到所有的np个节点,将请求的信息提取到一系列向量中,然后用结果创建一个 Dataframe 。

library(xml2)
library(dplyr)
npnodes <- xml_find_all(doc, ".//np") 
   
group <- npnodes %>% xml_find_first( "./ancestor::folder/group") %>% xml_text()
id <- npnodes %>% xml_find_first("./ancestor::folder/ID") %>% xml_text()
A <- npnodes %>% xml_find_first(".//A") %>% xml_text()
B <- npnodes %>% xml_find_first(".//B") %>% xml_text()
C <- npnodes %>% xml_find_first(".//C") %>% xml_text()
D <- npnodes %>% xml_find_first(".//D") %>% xml_text()
E <- npnodes %>% xml_find_first(".//E") %>% xml_text() 

answer <- data.frame(group,id, A, B, C, D, E)
answer

  group  id     A  B   C      D      E
1   800 ESK FIRST ES GOR   2021  -1000
2   800 ESK  TEST ES RUN 202303 202303
3   900 ABC   CAT ES  GO 202303   -500

相关问题