1

我有一个看起来像这样的 xml:

...
<node id=1>
 <child>a</child>
 <child>b</child>
 <child>c</child>
</node>
<node id=2>
 <child>d</child>
 <child>e</child>
</node>
...

我正在寻找的是一个 data.frame 指的是孩子各自的父母:

node_id  child_text
      1           a
      1           b
      1           c
      2           d
      2           e

我只能想到使用 xml2 的 2 个解决方案:

(a) 使用 xml_find_all(...) 创建一组子节点,然后使用 for 循环遍历 xml 结构以获取所需信息。显然效率极低。

(b) 得到一组父节点和一组子节点。从父集合中提取信息并计算每个父母有多少个孩子。然后使用 rep(information, no_of_children) 从上面填充 node_id 列。更好,但仍然愚蠢。

我认为必须有一种更有效的方法?我很高兴有任何建议,因为我现在使用这些方法一个多月了,同时处理千兆位的 - 效率极低的 xml 格式的数据结构。我也不限于使用 xml2,如果这会大大提高性能,我还可以切换到另一种编程语言。唯一重要的部分是我想从那里直接将数据加载到数据库中。

4

1 回答 1

0

鉴于您提供的非常通用的示例,我将rvestpurrr

x <- "<node id=1>
   <child>a</child>
   <child>b</child>
   <child>c</child>
  </node>
  <node id=2>
   <child>d</child>
   <child>e</child>
  </node>"


library(rvest)
library(purrr)

read_html(x) %>% 
  html_nodes('node') %>% 
  map_df(~{
    .x %>% 
      html_nodes('child') %>% 
      html_text() -> child
    data.frame(child = child, stringsAsFactors = FALSE)
  }, .id = 'node')

#>   node child
#> 1    1     a
#> 2    1     b
#> 3    1     c
#> 4    2     d
#> 5    2     e

还有一些基准可以与您的方法进行比较:

rbenchmark::benchmark(read_html(xml) %>% 
                        html_nodes('node') %>% 
                        map_df(~{
                          .x %>% 
                            html_nodes('child') %>% 
                            html_text() -> child
                          data.frame(child = child, stringsAsFactors = FALSE)
                        }, .id = 'node'), columns = c('replications', 'elapsed', 'user.self'))
#>   replications elapsed user.self
#> 1          100   0.964     0.964
于 2017-10-26T07:27:58.820 回答