R中使用mutate调用自定义函数时vapply报错的解决咨询
修复R中mutate调用自定义函数的长度不匹配错误
问题分析
当前的win_percent函数是为单个球队和单个日期设计的,但在mutate中调用时,传递的是整个Tm列和DateFull列(长度为2684的向量),函数内部处理后返回的结果长度与mutate期望的每行对应单个值的要求不匹配,因此触发错误。
另外原函数存在两处可优化点:
- 球队名称替换使用大量重复赋值,代码冗余
- 每行调用一次
mlb_standings,API请求次数过多,效率极低
修复方案
方案1:逐行处理(快速修改)
使用rowwise()让mutate逐行传递单个值给函数,同时用recode简化球队名称映射逻辑:
library(baseballr) library(tidyverse) win_percent <- function(Tm, DateFull) { # 合并两个联盟的 standings 数据 df <- rbind(mlb_standings(season = 2022, date = DateFull, league_id = 104), mlb_standings(season = 2022, date = DateFull, league_id = 103)) # 用recode简化球队全称到缩写的映射 df <- df %>% mutate(team_records_team_name = recode(team_records_team_name, "Baltimore Orioles" = "BAL", "Boston Red Sox" = "BOS", "Chicago White Sox" = "CHW", "Cleveland Guardians" = "CLE", "Detroit Tigers" = "DET", "Houston Astros" = "HOU", "Kansas City Royals" = "KCR", "Los Angeles Angels" = "LAA", "Minnesota Twins" = "MIN", "New York Yankees" = "NYY", "Oakland Athletics" = "OAK", "Seattle Mariners" = "SEA", "Tampa Bay Rays" = "TBR", "Texas Rangers" = "TEX", "Toronto Blue Jays" = "TOR", "Arizona Diamondbacks" = "ARI", "Atlanta Braves" = "ATL", "Chicago Cubs" = "CHC", "Cincinnati Reds" = "CIN", "Colorado Rockies" = "COL", "Los Angeles Dodgers" = "LAD", "Miami Marlins" = "MIA", "Milwaukee Brewers" = "MIL", "New York Mets" = "NYM", "Philadelphia Phillies" = "PHI", "Pittsburgh Pirates" = "PIT", "San Diego Padres" = "SDP", "San Francisco Giants" = "SFG", "St. Louis Cardinals" = "STL", "Washington Nationals" = "WSN" )) # 筛选目标球队并提取胜率 df %>% filter(team_records_team_name == Tm) %>% pull(team_records_winning_percentage) %>% as.numeric() } # 调用时添加rowwise()实现逐行处理 df %>% rowwise() %>% mutate(win_perc = win_percent(Tm, DateFull)) %>% ungroup() # 处理完成后取消逐行模式
方案2:向量化处理(高效推荐)
避免重复调用API,先获取所有唯一日期的standings数据,再与原数据框关联,大幅提升效率:
library(baseballr) library(tidyverse) # 1. 获取所有唯一日期的standings数据 unique_dates <- unique(df$DateFull) standings_list <- map(unique_dates, function(date) { rbind(mlb_standings(season = 2022, date = date, league_id = 104), mlb_standings(season = 2022, date = date, league_id = 103)) %>% mutate(DateFull = date) %>% # 球队全称转缩写 mutate(team_records_team_name = recode(team_records_team_name, "Baltimore Orioles" = "BAL", "Boston Red Sox" = "BOS", "Chicago White Sox" = "CHW", "Cleveland Guardians" = "CLE", "Detroit Tigers" = "DET", "Houston Astros" = "HOU", "Kansas City Royals" = "KCR", "Los Angeles Angels" = "LAA", "Minnesota Twins" = "MIN", "New York Yankees" = "NYY", "Oakland Athletics" = "OAK", "Seattle Mariners" = "SEA", "Tampa Bay Rays" = "TBR", "Texas Rangers" = "TEX", "Toronto Blue Jays" = "TOR", "Arizona Diamondbacks" = "ARI", "Atlanta Braves" = "ATL", "Chicago Cubs" = "CHC", "Cincinnati Reds" = "CIN", "Colorado Rockies" = "COL", "Los Angeles Dodgers" = "LAD", "Miami Marlins" = "MIA", "Milwaukee Brewers" = "MIL", "New York Mets" = "NYM", "Philadelphia Phillies" = "PHI", "Pittsburgh Pirates" = "PIT", "San Diego Padres" = "SDP", "San Francisco Giants" = "SFG", "St. Louis Cardinals" = "STL", "Washington Nationals" = "WSN" )) %>% select(DateFull, Tm = team_records_team_name, win_perc = team_records_winning_percentage) %>% mutate(win_perc = as.numeric(win_perc)) }) # 合并所有日期的standings数据 standings_df <- bind_rows(standings_list) # 2. 与原数据框关联,获取对应球队当日胜率 df_with_winperc <- df %>% left_join(standings_df, by = c("Tm", "DateFull"))
错误原因详解
mutate默认是向量化操作,会将整个列(向量)传递给函数。原函数中,当DateFull是长度2684的向量时,mlb_standings会被调用2684次,后续的filter和select逻辑在处理向量时出现长度不匹配,导致mutate无法将结果正确映射到每行数据,最终触发报错。
内容的提问来源于stack exchange,提问作者mjc0203
相关产品推荐
相关产品推荐

