如何优化足球数据集合并中的三层嵌套循环以提升代码效率?
优化足球数据集球员评分匹配的性能(避免嵌套循环)
核心思路
放弃三层嵌套循环,改用pandas向量化操作和**有序合并(merge_asof)**来实现,这两种方法是处理这类时间匹配+聚合场景的高效方案,能把时间复杂度从O(nmk)降到O(n log n + m log m)量级。
具体步骤
1. 预处理数据
首先把数据整理成适合批量处理的格式:
- 对球员评分数据按
player_id和date排序(merge_asof要求合并键必须有序) - 把比赛数据中的11名主场球员从宽表转成长表(将
home_player_1到home_player_11拆成每行对应一个球员+比赛日期的结构)
import pandas as pd # 预处理球员评分数据:按球员ID和日期排序 player_ratings = player_ratings.sort_values(by=["player_id", "date"]) # 确保日期是datetime类型 player_ratings["date"] = pd.to_datetime(player_ratings["date"]) # 预处理比赛数据:将主场球员列转成长表 matches["match_date"] = pd.to_datetime(matches["match_date"]) home_players_long = matches.melt( id_vars=["match_id", "match_date"], value_vars=[f"home_player_{i}" for i in range(1, 12)], value_name="player_id" ).dropna(subset=["player_id"]) # 剔除无效球员ID
2. 批量匹配最近日期的评分
用pd.merge_asof实现按球员ID匹配,取比赛日期之前最近的评分,这一步替代了循环遍历每个球员找评分的逻辑:
# 按球员ID合并,匹配比赛日期前最近的评分 matched_data = pd.merge_asof( home_players_long.sort_values("match_date"), player_ratings, left_on="match_date", right_on="date", by="player_id", direction="backward" # 只取<=比赛日期的最近记录 )
3. 聚合计算每场比赛的平均评分
按match_id分组聚合,直接计算每场比赛11名球员的评分平均值,替代循环遍历每场比赛的逻辑:
# 计算每场比赛的主场球员平均评分 match_avg_ratings = matched_data.groupby("match_id")["rating"].mean().reset_index() # 将平均评分合并回原比赛数据集 final_dataset = matches.merge(match_avg_ratings, on="match_id")
扩展优化(多属性计算)
如果需要计算多个属性(比如不同位置的平均评分、评分标准差等),只需在分组时指定对应的维度即可:
# 示例:按比赛ID+球员位置分组计算多指标 match_position_stats = matched_data.groupby(["match_id", "player_position"]).agg( avg_rating=("rating", "mean"), min_rating=("rating", "min"), max_rating=("rating", "max") ).reset_index()
额外性能提升点
- 给
player_ratings的player_id和date添加复合索引,加速排序和匹配:player_ratings = player_ratings.set_index(["player_id", "date"]).sort_index() - 确保所有日期列都是
datetime64类型,避免字符串匹配带来的性能损耗。
内容的提问来源于stack exchange,提问作者L. H.
相关产品推荐
相关产品推荐

