函数迭代列表,将结果合并到一个数据框

时间:2016-07-25 22:34:08

标签: r function for-loop dataframe

我已经完成了关于DataCamp的前几个R课程,为了增强我的技能,我决定使用R为本赛季的梦幻足球做准备,因此我开始玩nflscrapR包。

使用nflscrapR包,可以使用season_games()函数提取游戏信息,该函数只返回一个包含gameID,游戏日期,主队和客队缩写的数据框。

示例:

games.2012 = season_games(2012)
head(games.2012)
      GameID       date home away season
1 2012090500 2012-09-05  NYG  DAL   2012
2 2012090900 2012-09-09  CHI  IND   2012
3 2012090908 2012-09-09   KC  ATL   2012
4 2012090907 2012-09-09  CLE  PHI   2012
5 2012090906 2012-09-09   NO  WAS   2012
6 2012090905 2012-09-09  DET  STL   2012

最初我复制并粘贴了原始函数,并在每个季节手动更改了最后一位数字,然后将所有季节整理为一个数据框games

games.2012 <- season_games(2012)
games.2013 <- season_games(2013)
games.2014 <- season_games(2014)
games.2015 <- season_games(2015)
games = rbind(games2012,games2013,games2014,games2015)

我想写一个函数来简化这个过程。 我尝试失败了:

gameID <- function(years) {
  for (i in years) {
    games[i] = season_games(years[i])
  }
}

使用years = list(2012, 2013)进行测试,产生以下内容:

  

strsplit中的错误(标题,“\ r \ n”):非字符参数被调用   from:strsplit(headers,“\ r \ n”)

提前致谢!

2 个答案:

答案 0 :(得分:2)

虽然@Gregor有一个明显的解决方案,但他没有运行它,因为这不是一个最小的例子。我用Google搜索,发现并尝试使用此代码,但它不起作用,至少在非常重要的时间内。

另一方面,我从Vivek Patil的博客中获取了this code

library(XML)
weeklystats = as.data.frame(matrix(ncol = 14))  # Initializing our empty dataframe

names(weeklystats) = c("Week", "Day", "Date", "Blank",
                         "Win.Team", "At", "Lose.Team", 
                         "Points.Win", "Points.Lose", 
                         "YardsGained.Win", "Turnovers.Win", 
                         "YardsGained.Lose", "Turnovers.Lose",
                         "Year")  # Naming columns

URLpart1 = "http://www.pro-football-reference.com/years/"
URLpart3 = "/games.htm"

#### Our workhorse function ####

getData = function(URLpart1, URLpart3) {
  for (i in 2012:2015) {
    URL = paste(URLpart1, as.character(i), URLpart3, sep = "")
    tablefromURL = readHTMLTable(URL)
    table = tablefromURL[[1]]
    names(table) = c("Week", "Day", "Date", "Blank", "Win.Team", "At", "Lose.Team", 
                     "Points.Win", "Points.Lose", "YardsGained.Win", "Turnovers.Win", 
                     "YardsGained.Lose", "Turnovers.Lose")
    table$Year = i  # Inserting a value for the year 
    weeklystats = rbind(table, weeklystats)  # Appending happening here
  }
  return(weeklystats)
}

我发布了这个,因为它有效,你可能会学到一些你不知道的网页抓取,它会在11秒内运行。

system.time(weeklystats <- getData(URLpart1, URLpart3))
   user  system elapsed 
  0.870   0.014  10.926 

答案 1 :(得分:1)

您应该查看一些使用列表的热门答案,特别是How do I make a list of data frames?What's the difference between [ and [[?

没有理由把你的岁月放在list。它们只是整数,所以只需做一个普通的向量。

years = 2012:2015

然后我们可以让你的函数工作(我们需要在for循环之前初始化一个空列表):

gameID <- function(years) {
  games = list()
  for (i in years) {
    games[[i]] = season_games(years[i])
  }
  return(games)
}

请阅读上面的链接,了解我们将[[与列表和[一起使用向量的原因。我们可以像这样运行它:

game_list = gameID(2012:2015)

但这是这样的一个简单的功能,它更容易使用lapply。您的函数只是for循环的包装器,它返回list,而正是 lapply也是如此。但是,如果您的函数有season_games硬编码,lapply可以使用任何函数。

game_list = lapply(2012:2015, season_games)
# should be the same result as above

在任何一种情况下,我们都有数据框列表,并希望将其组合成一个大数据框。基本R方式为rbind do.call,但dplyrdata.table版本效率更高。

# pick your favorite
games = do.call(rbind, args = game_list)  # base
games = dplyr::bind_rows(game_list)
games = data.table::rbindlist(game_list)