【问题标题】:How to loop through year and month in a R function如何在R函数中循环年和月
【发布时间】:2021-07-11 15:41:20
【问题描述】:

我有一个网络抓取功能,它获取年份(期限)和月份(期限2)并将新闻标题作为数据框返回:

news <- function(term, term2) {
  
  html_dat <- read_html(paste0("https://news.google.com/search?q=site%3%2F",term,"%2F",term2,"&hl=en-US&gl=US&ceid=US%3Aen"))

  news_dat <- data.frame(
    Title = html_dat %>%
      html_nodes("a.DY5T1d") %>% 
      html_text()
  ) 

return(news_dat)
}

df <- news('2020', '05')

我想创建一个循环,它将参数从 2000 年到 2021 年以及每个月。例如,循环将接受参数 news('2000', '01') 然后迭代到 news('2000', '02')。

我想返回上述时间线中所有标题的数据框/列表。我的代码不起作用:


years <- 2000:2021
months <- 1:12

for (i in length(years)){
  for (j in length(months)){
    temp <- news(i,j)
  }
  newdf <- rbind(newdf, temp)
}

【问题讨论】:

  • length(years) 返回单个值。也许您想改用yearsseq_along(years)
  • 嘿,谢谢。这就说得通了!我将其更改为 seq_along(years),对于 temp
  • @purple1437 你得到这个错误是因为你在rbind 中使用它之前没有定义newdf。在循环之前将newdf 定义为空白数据框,并且应该解决错误。
  • newdf 未找到,因为在循环的第一次迭代中,newdf 不存在。顺便说一句,作为一般规则,如果您在 R 中使用`for` 循环,几乎可以肯定有更好的方法。这是一个典型的例子。
  • 如果我理解正确的话,library(tidyverse) newdf &lt;- tibble() %&gt;% expand(year=2000:2021, month=1:12) 是一个单行的 tidyverse 解决方案,可以满足您的需求。

标签: r


【解决方案1】:

您可以为此使用 purrr 包中的 map2_dfr

library(textreadr)
library(purrr)
library(rvest)

news <- function(term, term2) {

  url <-paste0("https://news.google.com/search?q=site%3%2F",term,"%2F",term2,"&hl=en-US&gl=US&ceid=US%3Aen")
  html_dat <- read_html(url)

  news_dat <- data.frame(
    Title = html_dat %>%
      html_nodes("a.DY5T1d") %>%
      html_text()
  )

}

years <- 2000:2021
months <- 1:12

crossArg <-cross_df(list(year=years, month=months))

df <- map2_dfr(crossArg$year, crossArg$month, news)

【讨论】:

    【解决方案2】:

    要记住的重要一点是,R 设计 用于处理列。例如,要给向量的每个元素加 1,这样写就足够了

    x <- 1:10
    x <- x + 1
    

    给出一个向量,其第一个元素是2,最后一个元素是11。因此,当您发现自己编写代码以循环遍历向量/矩阵/数据帧的 时,请停止。几乎肯定有更好的方法*。

    *:有罕见的,非常罕见的例外。这不是其中之一。

    library(tidyverse)
    
    newdf <- tibble() %>% expand(year=2000:2021, month=1:12)
    newdf
    # A tibble: 264 x 2
        year month
       <int> <int>
     1  2000     1
     2  2000     2
     3  2000     3
     4  2000     4
     5  2000     5
     6  2000     6
     7  2000     7
     8  2000     8
     9  2000     9
    10  2000    10
    # … with 254 more rows
    

    我相信这就是你想要的。

    编辑 为了阻止 OP 要求转换为字符,他们在其中一个 cmets 中暗示:

    newdf <- tibble() %>% 
               expand(year=2000:2021, month=1:12) %>% 
               mutate(year=as.character(year), month=as.character(month))
    

    newdf <- tibble() %>% 
               expand(year=as.character(2000:2021), month=as.character(1:12))
    

    虽然我认为这是不必要的。

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 2019-11-11
      • 2021-02-16
      • 2016-10-30
      • 1970-01-01
      相关资源
      最近更新 更多