在R中提取NHL嵌套列表数据并构建多比赛DataFrame的问题
解决方案:提取NHL多场比赛客队球员数据并添加GameId
1. 修复下标越界错误
你之前代码里的x[[1]]是多余的,nhl_games_boxscore返回的boxscores列表中,每个元素直接对应单场比赛的完整数据,不需要额外取[[1]]。修正后的客队球员提取代码:
away_players <- map(boxscores, \(x) x[["teams"]][["away"]][["players"]])
2. 正确提取球员数据并生成DataFrame
之前的代码把单场所有球员的信息合并成了一行,导致最终只有2行数据。正确的做法是对每个球员的嵌套列表单独扁平化,再合并:
结合添加gameId的需求,推荐用map2同时遍历比赛数据和对应的gameId,一次性完成数据提取与字段添加:
library(purrr) library(tidyr) library(dplyr) gameIds <- c(2023020001, 2023020002) boxscores <- nhl_games_boxscore(gameIds = gameIds) # 处理每场比赛的客队球员,绑定gameId并合并 df_away <- map2(boxscores, gameIds, function(boxscore, gid) { # 提取当前比赛的客队球员列表 players <- boxscore[["teams"]][["away"]][["players"]] # 逐个处理球员,扁平化后添加gameId map_dfr(players, function(player) { enframe(unlist(player)) %>% pivot_wider(names_from = name, values_from = value) %>% mutate(gameId = gid) }) }) %>% bind_rows()
3. 修复循环中的数据重复问题
你循环里的错误是每次都取第一场比赛的球员数据(boxscores[[1]]),而非当前循环的game_id对应场次。修正后的循环写法:
comb_away <- data.frame() for (game_id in gameIds) { # 仅获取当前game_id的单场boxscore single_boxscore <- nhl_games_boxscore(gameIds = game_id) # 提取当前比赛的客队球员(单场数据需取[[1]]) away_players <- single_boxscore[[1]][["teams"]][["away"]][["players"]] # 处理当前场次的球员数据并添加gameId res <- map_dfr(away_players, function(player) { enframe(unlist(player)) %>% pivot_wider(names_from = name, values_from = value) %>% mutate(gameId = game_id) }) comb_away <- rbind(comb_away, res) }
关键说明
map_dfr可以直接把列表中的数据框按行合并,替代map+bind_rows的组合,更简洁高效。- 扁平化球员数据时,
unlist会把嵌套列表转成键值对,再通过enframe+pivot_wider转成宽格式数据框,每个球员对应一行。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

