我的目标是将我的代码生成的嵌套列表转换成一个嵌套框架。我有下面的代码,它在一个循环中从几个url中提取一些数据,并将它们存储在列表中。
library(rvest)
library(XML)
library(purrr)
library(stringr)
library(dplyr)
# declare variables
month = c('07','09')
year = c('2022','2023')
day = c('040','050')
# initialize the empty list
final = list()
# perform the loop
for (i in year) {
for (j in month) {
for (k in day) {
skip_to_next <- FALSE
url <- paste0('https://www.baseball-reference.com/boxes/ARI/ARI', i, j, k, '.shtml')
Sys.sleep(5)
game_path <- tryCatch(url |>
read_html() |>
html_nodes(xpath = '//div[contains(@id, "batting")]') |>
map(\(x) x |>
as.character() |>
str_remove_all("<!--|-->") |>
read_html() |>
html_table()) |>
unlist(recursive = FALSE), error = function(e) {skip_to_next <<- TRUE} )
if(skip_to_next) {next}
url <- read_html(url)
list_url <- url %>%
html_nodes(xpath = "//td/a") %>%
html_text()
List_2_letters = as.list(list_url[nchar(list_url) > 5])
game_path <- mapply(cbind, game_path, "Date" = paste(gsub('.{1}$', '', k), j, i, sep = '-'), SIMPLIFY=F)
game_path <- Map(cbind, game_path, "Team" = List_2_letters)
final[[i]][[j]][[k]] <- game_path
}
}
}
字符串
我得到一堆列表,看起来像下面这样:
的数据
我尝试做的是合并所有具有data.frame
值的列表。
我尝试了所有这些:
final_2 = map_dfr(final, ~ bind_rows(.x))
final_2 <- as.data.frame(do.call(cbind, final))
final_2 <- do.call("rbind", final)
型
但他们都只是产生2名单并排。我其实很卡住,至于如何才能解决这个问题?
1条答案
按热度按时间2izufjch1#
你可以通过不创建一个嵌套列表来更容易地实现你想要的结果。我重构了你的代码,首先将主要的抓取代码放在一个函数中,以便于调试和测试。在这个函数中,我已经使用
dplyr::bind_rows
将团队表绑定到一个框架中。这个函数也应该更有效,因为它避免了像你的代码那样阅读两次HTML。对于循环部分,我切换到
purrr::map
。为此,创建一个包含日期和相应URL的嵌套框架。这样,您可以直接在URL上循环,而不需要嵌套for循环。因此,您将获得一个嵌套框架列表,您最终可以按行绑定在一起。最后,请注意,我删除了
tryCatch
,并使用purrr::safely
来处理错误。字符串
EDIT问题是列的数据表从日期到日期不同,即,对于2022-07-04,
WPA-
列被读取为character
,因为值包括%
符号,而对于2023-07- 04它只包含一个数字,因此被读取为numeric
。为了解决这个问题,我们需要在绑定表之前做一些数据清理。下面的代码将步骤分成几部分。首先,使用结果提取表。然后循环遍历字符框列表,并使用例如readr::parse_number
将应该是数字的字符列转换为数字。这样做之后,绑定原则上应该工作。我测试了2022年和2023年。当然,也可能出现其他问题。一个更安全的选择是将所有列转换为字符。然后绑定。然后进行数据清理,最后将列转换为数字。型