Python/R:当并非所有节点都包含所有变量时,从 XML 生成数据帧?

2023-12-24

考虑以下XML example

library(xml2)

myxml <- read_xml('
<data>
  <obs ID="a">
  <name> John </name>
  <hobby> tennis </hobby>
  <hobby> golf </hobby>
  <skill> python  </skill>
  </obs>
  <obs ID="b">
  <name> Robert </name>
  <skill> R </skill>
  </obs>
  </data>
')

在这里,我想从包含列的 XML 中获取一个(R 或 Pandas)数据框name and hobby.

然而,正如你所看到的,存在对齐问题,因为hobby第二个节点中缺少 ,并且约翰有两个爱好。

在 R 中,我知道如何一次提取一个特定值,例如使用xml2如下:

myxml%>% 
  xml_find_all("//name") %>% 
  xml_text()

myxml%>% 
  xml_find_all("//hobby") %>% 
  xml_text()

但如何在数据框中正确对齐这些数据?也就是说,我如何获取数据框,如下所示(注意我如何加入|约翰的两个爱好):

# A tibble: 2 × 3
    name           hobby            skill
   <chr>           <chr>            <chr>
1   John          tennis|golf       python
2 Robert            <NA>            R

在 R 中,我更喜欢使用以下解决方案xml2 and dplyr。在 Python 中,我想最终得到一个 Pandas 数据框。另外,在我的 xml 中还有更多我想要解析的变量。我想要一个允许用户解析附加变量而又不会过多地干扰代码的解决方案。

Thanks!

编辑:感谢大家提供这些出色的解决方案。所有这些都非常好,有很多细节,很难选出最好的一个。再次感谢!


不需要对变量进行硬编码的通用 R 解决方案。
Using xml2和 tidyverse 的purrr:

library(xml2)
library(purrr)

myxml %>% 
  xml_find_all('obs') %>%      
  # Enter each obs and return a df
  map_df(~{

    # Scan names
    node_names <- .x %>% 
      xml_children() %>% 
      xml_name() %>%
      unique()        

    # Remember ob
    ob <- .x

    # Enter each node
    map(node_names, ~{

      # Find similar nodes
      node <- xml_find_all(ob, .x) %>%
        xml_text(trim = TRUE) %>%
        paste0(collapse = '|') %>% 
        'names<-'(.x)
        # ^ we need to name the element to 
        #   overwrite it with its 'sibilings'

    }) %>% 
      # Return an 'ob' vector
      flatten()        
  })

#> # A tibble: 2 × 3
#>     name       hobby  skill
#>    <chr>       <chr>  <chr>
#> 1   John tennis|golf python
#> 2 Robert        <NA>      R

它能做什么:

  1. 它“进入”每个obs,在该 obs 中查找并存储节点名称。
  2. 对于每个节点,找到所有相似的节点obs,折叠它们并存储在列表中。
  3. 展平列表,覆盖具有相同名称的元素。
  4. rbind(隐含在map_df())将每个“扁平化”列表放入结果中data.frame.

Data:

myxml <- read_xml('
                  <data>
                  <obs ID="a">
                  <name> John </name>
                  <hobby> tennis </hobby>
                  <hobby> golf </hobby>
                  <skill> python  </skill>
                  </obs>
                  <obs ID="b">
                  <name> Robert </name>
                  <skill> R </skill>
                  </obs>
                  </data>
                  ')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python/R:当并非所有节点都包含所有变量时,从 XML 生成数据帧? 的相关文章

随机推荐