考虑以下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
它能做什么:
- 它“进入”每个
obs
,在该 obs 中查找并存储节点名称。
- 对于每个节点,找到所有相似的节点
obs
,折叠它们并存储在列表中。
- 展平列表,覆盖具有相同名称的元素。
-
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(使用前将#替换为@)