xml2 - более эффективно получать информацию из родительских узлов

У меня есть 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

Есть только 2 решения, которые я мог бы подумать об использовании xml2:

(a) создайте набор дочерних узлов, используя xml_find_all (...), а затем используйте цикл for для маневрирования через структуру xml для получения необходимой информации. Крайне неэффективно, очевидно.

(б) получить набор родительских узлов и набор дочерних узлов для каждого. Извлеките информацию из родительского набора и посчитайте, сколько детей у каждого из родителей. Затем использовал rep (information, no_of_children), чтобы заполнить столбец node_id сверху. Лучше, но все еще глупо.

Я предполагаю, что должен быть более эффективный способ? Я рад любому предложению, поскольку я использую эти подходы уже более месяца, имея дело с гигабитами - крайне неэффективных - структур данных в формате xml. Я также не ограничиваюсь использованием xml2 и могу также переключиться на другой язык программирования, если это значительно повысит производительность. Единственной важной частью является то, что я хотел бы загрузить данные непосредственно в базу данных оттуда.

1 ответ

Учитывая очень общий пример, который вы дали, я бы использовал rvest вместе с purrr:

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
Другие вопросы по тегам