【问题标题】:How to resolve 'Don't know how to pluck from a closure' error in R如何解决 R 中的“不知道如何从闭包中提取”错误
【发布时间】:2019-01-13 03:23:39
【问题描述】:

如果我从 map() 函数中删除 Sys.sleep(),则下面的代码有效。我试图研究错误('不知道如何从闭包中提取'),但我没有找到关于该主题的太多内容。

有谁知道我在哪里可以找到有关此错误的文档,以及有关它发生的原因以及如何防止它的任何帮助?

library(rvest)
library(tidyverse)
library(stringr)

# lets assume 3 pages only to do it quickly
page <- (0:18)

# no need to create a list. Just a vector
urls = paste0("https://www.mlssoccer.com/players?page=", page)

# define this function that collects the player's name from a url
get_the_names = function( url){
  url %>% 
    read_html() %>% 
    html_nodes("a.name_link") %>% 
    html_text()
}

# map the urls to the function that gets the names
players = map(urls, get_the_names) %>% 
# turn into a single character vector
unlist() %>% 
# make lower case
tolower() %>% 
# replace the `space` to underscore
str_replace_all(" ", "-")


# Now create a vector of player urls
player_urls = paste0("https://www.mlssoccer.com/players/", players )


# define a function that reads the 3rd table of the url
get_the_summary_stats <-  function(url){

  url %>% 
    read_html() %>% 
    html_nodes("table") %>% 
    html_table() %>% .[[3]]

}

# lets read 3 players only to speed things up [otherwise it takes a significant amount of time to run...]
a_few_players <- player_urls[1:5]

# get the stats 
tables = a_few_players %>% 
# important step so I can name the rows I get in the table
set_names() %>% 
#map the player urls to the function that reads the 3rd table
# note the `safely` wrap around the get_the_summary_stats' function
# since there are players with no stats and causes an error (eg.brenden-aaronson )
# the output will be a list of lists [result and error]
map(., ~{ Sys.sleep(5) 
  safely(get_the_summary_stats) }) %>%
# collect only the `result` output (the table) INTO A DATA FRAME
# There is also an `error` output
# also, name each row with the players name
map_df("result", .id = "player") %>% 
#keep only the player name (remove the www.mls.... part)
mutate(player = str_replace(player, "https://www.mlssoccer.com/players/", "")) %>%
as_tibble()

tables <- tables %>% separate(Match,c("awayTeam","homeTeam"), extra= "drop", fill = "right")

【问题讨论】:

  • purrr::safely(...) 返回一个函数,因此您的 map(., { Sys.sleep(5); safely(get_the_summary_stats) }) 返回函数,而不是任何数据。在 R 中,“闭包”是一个函数及其封闭环境。也许你的意思是map(., ~safely(get_the_summary_stats)(.))?
  • 最后的 (.) 有什么作用?
  • 波浪符号是tidyverse 特有的更简洁匿名函数的方法。通常(例如,使用lapply)会使用lapply(mydata, function(x) get_the_summary_stats(x))。在波浪符号中,同样的东西写成map(mydata, ~ get_the_summary_stats(.))。
  • (我应该注意这个“波浪符号”是 tidyverse 独有的,不一定在其他函数中可用。我相信它实际上是在 rlang 中完成的,这是许多tidyverse 包,但我不确定在哪里。)
  • 谢谢。插入 Sys.sleep() 的正确位置在哪里?

标签: r tidyverse purrr


【解决方案1】:

purrr::safely(...) 返回一个函数,因此您的 map(., { Sys.sleep(5); safely(get_the_summary_stats) }) 返回的是函数,而不是任何数据。在 R 中,“闭包”是一个函数及其封闭环境。

波浪符号是更简洁的匿名函数的一种特定于 tidyverse 的方法。通常情况下(例如,lapply) 将使用 lapply(mydata, function(x) get_the_summary_stats(x))。在波浪符号中,同样的事情写成 map(mydata, ~ get_the_summary_stats(.))

所以,重写:

... %>% map(~ { Sys.sleep(5); safely(get_the_summary_stats)(.); })

来自@r2evans的cmets

【讨论】:

    猜你喜欢
    • 2022-01-05
    • 2014-10-31
    • 2021-07-15
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多