将 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
我在 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