如何在Pandas DataFrame中按年份保留无序列对的唯一行
处理Pandas DataFrame中无序列对的重复行问题
问题背景
有一个包含多列的Pandas DataFrame,其中SOMMET_1和SOMMET_2两列存在数据置换的重复行(比如同一YEAR下,(A,B)和(B,A)视为同一组),需要针对每个YEAR值,仅保留这两列无序排列的唯一行,并按SOMMET_1字母顺序排序。
示例DataFrame:
import pandas as pd df = pd.DataFrame([[2017, 'MTEZ5P71', 'MTEZIP71', 0.395508, 5.078320], [2017, 'MTEZ5P71', 'RUEYRP71', 0.395508, 5.078320], [2022, 'MTEZ5P71', 'RUEYRP71', 0.006328, 25.435898], [2022, 'RUEYRP71', 'MTEZ5P71', 0.006328, 25.435898], [2022, 'ARGIAP71', '.HERN 71', 1.180195, 12.507539]], columns=['YEAR', 'SOMMET_1', 'SOMMET_2', 'R', 'X'])
原始数据表格:
| YEAR | SOMMET_1 | SOMMET_2 | R | X |
|---|---|---|---|---|
| 2017 | MTEZ5P71 | MTEZIP71 | 0.395508 | 5.078320 |
| 2017 | MTEZ5P71 | RUEYRP71 | 0.395508 | 5.078320 |
| 2022 | MTEZ5P71 | RUEYRP71 | 0.006328 | 25.435898 |
| 2022 | RUEYRP71 | MTEZ5P71 | 0.006328 | 25.435898 |
| 2022 | ARGIAP71 | .HERN 71 | 1.180195 | 12.507539 |
尝试过直接按SOMMET_1和SOMMET_2分组:
df.groupby(['SOMMET_1', 'SOMMET_2'])['YEAR']
但这种方式无法识别无序的列对重复(比如(MTEZ5P71, RUEYRP71)和(RUEYRP71, MTEZ5P71)会被当成不同分组)。
解决方案
核心思路是为每个无序列对生成唯一标识,再基于YEAR和该标识去重,最后排序。
步骤1:生成无序列对的唯一标识
对每行的SOMMET_1和SOMMET_2按字母顺序排序,拼接成元组作为临时列unique_pair,这样(A,B)和(B,A)会生成相同的标识:
df['unique_pair'] = df.apply(lambda row: tuple(sorted([row['SOMMET_1'], row['SOMMET_2']])), axis=1)
步骤2:按YEAR和唯一标识去重
按YEAR和unique_pair分组,保留每组的第一行(因为同一组的R、X值一致,任意一行都可以):
df_unique = df.groupby(['YEAR', 'unique_pair']).first().reset_index()
步骤3:清理临时列并排序
删除临时列unique_pair,然后按YEAR和SOMMET_1字母顺序排序:
df_unique = df_unique.drop('unique_pair', axis=1).sort_values(by=['YEAR', 'SOMMET_1']).reset_index(drop=True)
完整代码
import pandas as pd df = pd.DataFrame([[2017, 'MTEZ5P71', 'MTEZIP71', 0.395508, 5.078320], [2017, 'MTEZ5P71', 'RUEYRP71', 0.395508, 5.078320], [2022, 'MTEZ5P71', 'RUEYRP71', 0.006328, 25.435898], [2022, 'RUEYRP71', 'MTEZ5P71', 0.006328, 25.435898], [2022, 'ARGIAP71', '.HERN 71', 1.180195, 12.507539]], columns=['YEAR', 'SOMMET_1', 'SOMMET_2', 'R', 'X']) # 生成唯一无序对标识 df['unique_pair'] = df.apply(lambda row: tuple(sorted([row['SOMMET_1'], row['SOMMET_2']])), axis=1) # 按年份和唯一对去重 df_unique = df.groupby(['YEAR', 'unique_pair']).first().reset_index() # 清理并排序 df_unique = df_unique.drop('unique_pair', axis=1).sort_values(by=['YEAR', 'SOMMET_1']).reset_index(drop=True) print(df_unique)
最终结果
| YEAR | SOMMET_1 | SOMMET_2 | R | X |
|---|---|---|---|---|
| 2017 | MTEZ5P71 | MTEZIP71 | 0.395508 | 5.078320 |
| 2017 | MTEZ5P71 | RUEYRP71 | 0.395508 | 5.078320 |
| 2022 | ARGIAP71 | .HERN 71 | 1.180195 | 12.507539 |
| 2022 | MTEZ5P71 | RUEYRP71 | 0.006328 | 25.435898 |
内容的提问来源于stack exchange,提问作者LGDiaz
相关产品推荐
相关产品推荐

