我正在尝试使用rvest
从FiveThirtyEight获取每日预测,但我感兴趣的对象似乎是一个javascript对象,我甚至很难找到寻找的位置和内容。 (虽然我在过去几天试图教育自己,但我并不精通CSS或Javascript。)
通过检查网页元素和CSS选择器,我发现了以下内容:
要查看的位置是<div id="polling-avg-chart">
,所以我尝试了
library(rvest)
url <-
"https://projects.fivethirtyeight.com/election-2016/national-primary-polls/democratic/"
url %>%
read_html() %>%
html_nodes("#polling-avg-chart")
没有太大的成功。输出只是
{xml_nodeset(1)}
[1]&lt; \ div id =&#34; polling-avg-chart&#34;&gt;&lt; / div&gt; \ n
单个民意调查结果中的点位于<g style="clip-path: url("#line-clippoll_avg");"> ... </g>
,您可以在其中看到502个数字位置。我猜我必须将每个节点的cx
和cy
翻译成适当的百分比,这由<g class="flag-box" transform="translate(30, 161.44093322753096)">...</g>
完成,依此类推。
但是,我没有看到预测线的基础数据,而不是点。
<line class="hover-date-line hide-line">
之类的内容发生了变化,<path class="link" d="M 0 171.40106812500002 C 15 171.40106812500002 15 170.94093803735575 30 170.94093803735575"></path>
之类的值发生了变化,我猜这些值是什么&#39} ; s创建每日预测线。我确实阅读了其他一些SO帖子,例如this,但它们似乎都不适用于这个特定问题。在整洁的数据框架中获得预测百分比的最佳方法是什么?
答案 0 :(得分:1)
这里的图表几乎肯定是用d3.js或它上面的包装器构建的。 d3非常适合构建基于svg的数据可视化,因为它可以帮助您构建比例尺以将值(例如40%)映射到屏幕上的展示位置(例如您看到的内容,例如cx=100
)。问题是你需要知道那些尺度是什么,以便获得基础数据,并且尺度可能是动态的,并且会根据屏幕尺寸等而变化。
相反,由于数据位于下表中,您可以轻松地将其删除。该表位于标识为div
的{{1}}元素内,并且具有类latest-polls
。
我正在使用t-polls
和CSS选择器html_node
将表格转换为数据框,清理名称,并将数字列转换为实际的数字列。接下来你可以做更多的事情,比如格式化日期,但希望这能让你开始。
html_table
答案 1 :(得分:1)
另一种方法是直接获取资源。
在浏览器中,打开开发人员工具(Chrome / Chromium中的 F12 ),前往&#34;网络&#34;,刷新( F5 ),然后查看看起来像一个格式很好的JSON。当我们找到它时,我们会复制链接地址(右键单击资源&gt;复制链接地址)。
library(httr)
library(tidyr)
library(purrr)
library(dplyr)
library(ggplot2)
url <- "https://projects.fivethirtyeight.com/election-2016/national-primary-polls/USA.json"
r <- GET(url)
整个数据都存在。权重也是如此,因此您可以重新计算这些平均值。绘制的数据位于"model"
:
dat <-
jsonlite::fromJSON(content(r, as = "text")) %>%
map(purrr::pluck, "model") %>%
bind_rows(.id = "party") %>%
mutate_all(readr::parse_guess)
# # A tibble: 5,288 x 5
# party candidate_name state forecastdate poll_avg
# <chr> <chr> <chr> <date> <dbl>
# 1 D Sanders USA 2016-07-01 36.5
# 2 D Clinton USA 2016-07-01 55.4
# 3 D Sanders USA 2016-06-30 37.0
# 4 D Clinton USA 2016-06-30 54.6
# 5 D Sanders USA 2016-06-29 37.0
# 6 D Clinton USA 2016-06-29 54.9
# 7 D Sanders USA 2016-06-28 37.2
# 8 D Clinton USA 2016-06-28 54.4
# 9 D Sanders USA 2016-06-27 37.4
# 10 D Clinton USA 2016-06-27 53.9
# # ... with 5,278 more rows
重现图表:
dat %>%
filter(candidate_name %in% c("Clinton", "Kasich", "Sanders", "Trump")) %>%
ggplot(aes(forecastdate, poll_avg)) +
geom_line(aes(col = candidate_name)) +
facet_wrap(~party)
如果你喜欢互动:
library(dygraphs)
library(htmltools)
foo <- dat %>%
filter(candidate_name %in% c("Clinton", "Kasich", "Sanders", "Trump")) %>%
split(.$party) %>%
map(~ {
select(.x, forecastdate, candidate_name, poll_avg) %>%
spread(candidate_name, poll_avg) %>%
{xts(.[-1], .[[1]])} %>%
dygraph(group = "poll-model") %>%
dyRangeSelector()
})
browsable(tagList(foo))