R语言如何批量对20个数据框字段执行关联并修复代码错误?
问题1:批量关联20个playerID字段的实现方案
你可以通过「宽表转长表-单次关联-长表转宽表」的逻辑实现全量字段批量匹配,完全不需要逐字段硬编码写left_join,计算效率远高于逐次关联:
- 效率优势:逐次left_join需要对主表执行20次全表扫描和匹配计算,长表方案只需要执行1次关联操作,数据量越大性能提升越明显
- 实现代码逻辑:
# 第一步:先定义所有需要匹配的playerID字段名,只需要维护这一个向量即可 id_cols <- c( "VisitorStartingPitcherID", paste0("VisitorBatting", 1:9, "PlayerID"), "HomeStartingPitcherID", paste0("HomeBatting", 1:9, "PlayerID") ) # 第二步:预先处理好关联用的Appearance映射表 Appearance <- Lahman::Appearances %>% filter(yearID <= i) %>% group_by(playerID) %>% summarise(GS = sum(GS)) %>% # 这里同步修正字段名错误:选的是key_retro,就要用key_retro重命名 left_join(Chadwick, by = c("playerID" = "bbrefID")) %>% select(playerID = key_retro, GS) # 第三步:长表转换后单次关联,再转回宽表生成所有GS字段 Retro_Temp_with_gs <- Retro_Temp %>% mutate(row_id = row_number()) %>% # 保留原行索引,用于后续拼接 pivot_longer(cols = all_of(id_cols), names_to = "id_col", values_to = "playerID") %>% left_join(Appearance, by = "playerID") %>% # 一次关联搞定所有ID匹配 mutate(gs_col = paste0(id_col, "GS")) %>% select(row_id, gs_col, GS) %>% pivot_wider(names_from = gs_col, values_from = GS) %>% # 把GS字段拼回原主表 left_join(Retro_Temp %>% mutate(row_id = row_number()), ., by = "row_id") %>% select(-row_id)
问题2:现有代码错误排查
你代码里的错误主要是4处,全部修正后就能正常输出主客队结果:
- 映射表字段名错误:你在处理Appearance表时,
select(key_retro,GS) %>% rename(playerID = retroID)这里选出来的列是key_retro,但rename的源列名写成了不存在的retroID,导致最终生成的Appearance表playerID全为NA,后续主场ID匹配全部失败,改成rename(playerID = key_retro)即可。 - 索引逻辑写反:计算
Home_most_GS时你写的是.[33,43:52],逗号分隔行和列索引,相当于只取了第33行的43-52列,所有行的计算结果都复用了第33行的值,正确写法是去掉行索引:.[,43:52]。 - 索引范围错误:计算
Vistor_most_GS时你写的是.[33:43],选的是第33到43列,对应的是主场GS字段范围,取到的全是主场球员的数据,自然没有客队正确结果。另外硬编码数字索引非常不稳定,只要前面字段数量变化就会出错,推荐用列名特征筛选GS字段。 - 拼写错误:你把Visitor拼成了Vistor,后续过滤条件里的字段名和生成的字段名不匹配,也会导致过滤结果异常。
你可以把计算最大GS字段的逻辑替换为下面的代码,稳定性更高:
Retro_Temp3 <- Retro_Temp2 %>% rowwise() %>% mutate( # 直接通过列名前缀后缀筛选主客队GS字段,不需要硬编码索引 Home_most_GS = names(select(., starts_with("Home") & ends_with("GS")))[which.max(c_across(starts_with("Home") & ends_with("GS")))], Visitor_most_GS = names(select(., starts_with("Visitor") & ends_with("GS")))[which.max(c_across(starts_with("Visitor") & ends_with("GS")))] ) %>% ungroup()
内容的提问来源于stack exchange,提问作者RuffGriffin
相关产品推荐
相关产品推荐

