通过Glob合并多个CSV文件,解决重复行问题并生成目标Pandas DataFrame(保留NaN值)
你现在碰到的问题应该是合并完CSV之后,同一个Player Name加Team的记录被拆成了好几行,每行只带着某一轮的数据对吧?想要把这些行合并成一条完整记录,还得保留原始的NaN值,我给你个靠谱的解决方案:
直接可用的代码
import pandas as pd from glob import glob # 先按你原来的方式把所有CSV合并起来 df = pd.concat(map(pd.read_csv, sorted(glob(f"{Year}*.csv"), key=len)), join='outer', ignore_index=True, axis=0) # 核心合并步骤:按球员和队伍分组,聚合同一组的行 merged_df = df.groupby(['Player Name', 'Team'], as_index=False).agg( lambda col: col.dropna().iloc[0] if not col.dropna().empty else pd.NA )
或者如果你觉得上面的lambda有点绕,用填充的方式也能搞定(适合你这种同组内各列非NaN值不重复的场景):
merged_df = df.groupby(['Player Name', 'Team'], as_index=False).apply( lambda group: group.ffill().bfill().iloc[0] )
为啥这个方法管用?
- 分组逻辑:用
Player Name和Team当分组键,确保同一个球员同一只队伍的所有记录都被归到一组里。 - 聚合/填充逻辑:
- 第一种方法的lambda函数:对每个列,先把NaN去掉,取剩下的第一个值(因为你每组里同一列只有一个有效数据),如果全是NaN就保留NaN,完美匹配你的需求。
- 第二种方法的
ffill().bfill():先把组里的缺失值向前填充,再向后填充,这样同一组的所有行都会变成完整的记录,最后取每组第一行就行。
测试一下结果
用你给的示例数据跑这两段代码,都会得到你想要的理想输出:
Player Name Team Round 1 Round 2 0 Player A Team A 100.0 110.0 1 Player B Team B 200.0 210.0 2 Player C Team A NaN NaN
为啥你之前的尝试没成?
估计是用groupby的时候选了不合适的聚合函数,比如sum()或者mean()会改原始值,用merge的时候没处理好重复键的情况。而上面的方法刚好贴合你的数据特点——同一组内同一列只有一个有效数据,所以能精准保留原始值,还合并了重复行。
要是你的数据里出现同一球员同队在同一轮有多个有效分数的情况,你可以调整聚合函数(比如改成求和、取平均),不过根据你的描述应该不会有这种情况~
内容的提问来源于stack exchange,提问作者Fonti
相关产品推荐
相关产品推荐

