将 xml 导入到 R

Import xml to R

我在 xml 文件中有选举结果数据,我正在尝试将其导入 R。这是我第一次使用 xml 文件,但我完全不知道发生了什么使用我可以下载的 .xls 版本的数据,所以我正在尝试使用 xml.

没有直接 link 到 xml 文件,但可以在此处 https://results.enr.clarityelections.com/IL/Bloomington/109017/web.276013/#/summary 右侧通过稍微向下滚动到“报告”来访问它正在下载“详细信息 XML”。

我一直在尝试使用 xml2 将其放入数据框中。我可以 read_xml 然后将它变成一个列表,但在那之后我的尝试只给我提供了各种错误或更多包含大量 NULL 的列表。 xml 文件本身可能会造成这种怪异现象,但我对它们的了解还不够多,无法判断是否属于这种情况。

没有输出 gioven,所以这是开始的东西..

目标:按地区提取选民投票率数据(xml第一部分)

library(tidyverse)
library(xml2)

doc <- xml2::read_xml("./detail.xml")

# get the voter turnout-nodes
nodes <- 
# build df
df <- xml2::xml_find_all(doc, ".//VoterTurnout/Precincts/Precinct") %>%
  purrr::map(xml_attrs) %>%
  purrr::map_df(as.list)

# A tibble: 52 x 5
name        totalVoters ballotsCast voterTurnout percentReporting
<chr>       <chr>       <chr>       <chr>        <chr>           
1 Precinct 1  709         185         26.09        4               
2 Precinct 2  932         154         16.52        4               
3 Precinct 3  849         292         34.39        4               
4 Precinct 4  1128        178         15.78        4               
5 Precinct 5  846         165         19.50        4               
6 Precinct 6  1437        188         13.08        4               
7 Precinct 7  1459        165         11.31        4               
8 Precinct 8  558         193         34.59        4               
9 Precinct 9  1320        183         13.86        4               
10 Precinct 10 1292        444         34.37        4 
...

这是我最终得到的解决方案:在尝试构建数据框之前使用 XSLT 重构 xml。解决方案的基础来自 (巧合的是也关于选举数据)。

XSLT - 将其重组为每个选区节点的一长串列表,并将来自他们的选择、竞赛和投票类型祖先的适用信息作为属性。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/ElectionResult">
    <xsl:copy>
      <xsl:apply-templates select="descendant::Precinct"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Precinct">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="election">
        <xsl:value-of select="ancestor::ElectionResult/ElectionName"/>
      </xsl:attribute>
      <xsl:attribute name="contest">
        <xsl:value-of select="ancestor::Contest/@text"/>
      </xsl:attribute>
      <xsl:attribute name="choice">
        <xsl:value-of select="ancestor::Choice/@text"/>
      </xsl:attribute>
      <xsl:attribute name="votetype">
        <xsl:value-of select="ancestor::VoteType[1]/@name"/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

R - xslt 包作为 xml2 的扩展来应用 .xsl 文件。

library(xml2)
library(xslt)
library(tidyverse)

# Parse XML and XSL
xml <- read_xml("electionresults.xml")
style <- read_xml("style.xsl", package = "xslt")

# Transform XML
new_xml <- xslt::xml_xslt(xml, style)

# Build data frame
elections <- new_xml %>% 
  xml_find_all("//Precinct") %>% 
  map_dfr(~list(election = xml_attr(., "election"),
                contest = xml_attr(., "contest"),
                choice = xml_attr(., "choice"),
                votetype = xml_attr(., "votetype"),
                precinct = xml_attr(., "name"),
                votes = xml_attr(., "votes"))) %>% 
  type_convert()

构建数据框的映射过程来自R XML - combining parent and child nodes into data frame