基于带时间容差的公共列提取行时出现重复结果问题
问题原因
你的代码会生成所有满足容差条件的df1和df2行的组合,导致笛卡尔积式的重复:
- df1前11行的
YearDeci(2008.5051149999999)如果匹配df2前10行的YearDeci(2008.5051180000000),就会产生11×10=110条记录 - df1最后2行的
YearDeci(2008.5253180000000)如果匹配df2中间4行的YearDeci(2008.5253200000000),又会产生2×4=8条记录 - 最终110+8=118条记录,这就是重复的来源
解决方案
如果你需要输出和df1行数一致的15行结果,需要为每个df1的行匹配唯一的df2行(或匹配df2中同组YearDeci的聚合结果),以下是几种可行方案:
方案1:匹配df2中第一个符合条件的行
为df1的每一行找到df2中第一个满足容差的行,无匹配则保留NaN:
import numpy as np import pandas as pd dt = 1.8973892110807355e-06 # 计算所有匹配对 tmp = np.isclose(df1.YearDeci[:, np.newaxis], df2.YearDeci[np.newaxis, :], atol=dt, rtol=0) # 找到每个df1行对应的第一个匹配的df2索引 first_match_idx = np.argmax(tmp, axis=1) # 标记哪些df1行有有效匹配 has_match = np.any(tmp, axis=1) # 构建匹配关系表 match_df = pd.DataFrame({ 'ind1': df1.index, 'ind2': first_match_idx }) # 仅保留有匹配的行,无匹配的ind2设为NaN match_df.loc[~has_match, 'ind2'] = np.nan # 合并得到结果 result = df1.merge(match_df, left_index=True, right_on='ind1', how='left') result = result.merge(df2, left_on='ind2', right_index=True, suffixes=['_temp1', '_temp2'], how='left') # 清理冗余列 result = result.drop(['ind1', 'ind2'], axis=1)
方案2:先对df2按YearDeci去重再匹配
如果df2中同一YearDeci的行内容重复,可以先去重,再匹配,确保每个df1行只对应一个df2行:
# 对df2按YearDeci去重,保留第一个出现的行 df2_unique = df2.drop_duplicates(subset='YearDeci').reset_index(drop=True) # 计算匹配关系 tmp = np.isclose(df1.YearDeci[:, np.newaxis], df2_unique.YearDeci[np.newaxis, :], atol=dt, rtol=0) first_match_idx = np.argmax(tmp, axis=1) has_match = np.any(tmp, axis=1) match_df = pd.DataFrame({ 'ind1': df1.index, 'match_year_idx': first_match_idx }) match_df.loc[~has_match, 'match_year_idx'] = np.nan # 合并 result = df1.merge(match_df, left_index=True, right_on='ind1', how='left') result = result.merge(df2_unique, left_on='match_year_idx', right_index=True, suffixes=['_temp1', '_temp2'], how='left') result = result.drop(['ind1', 'match_year_idx'], axis=1)
方案3:聚合df2同YearDeci的结果再匹配
如果需要将df2中同一YearDeci的rms值做聚合(比如取均值),再和df1合并:
# 对df2按YearDeci分组,聚合rms(这里用均值,可根据需求改为其他聚合方式) df2_grouped = df2.groupby('YearDeci').agg({'rms': 'mean'}).reset_index() # 计算匹配关系 tmp = np.isclose(df1.YearDeci[:, np.newaxis], df2_grouped.YearDeci[np.newaxis, :], atol=dt, rtol=0) first_match_idx = np.argmax(tmp, axis=1) has_match = np.any(tmp, axis=1) # 合并 df1['match_idx'] = first_match_idx df1.loc[~has_match, 'match_idx'] = np.nan result = df1.merge(df2_grouped, left_on='match_idx', right_index=True, suffixes=['_temp1', '_temp2'], how='left') result = result.drop('match_idx', axis=1)
额外提醒
请确认你的容差dt是否正确:
计算df1的2008.5051149999999和df2的2008.5051180000000的差值为3.0000001e-06,而你的dt=1.897e-06,这个差值超过了容差,理论上不应该匹配。如果实际代码中它们被判定为匹配,可能是浮点数精度问题,建议手动验证差值是否真的在容差范围内:
# 验证差值 diff = abs(df1.YearDeci.iloc[0] - df2.YearDeci.iloc[0]) print(f"差值: {diff}, 容差: {dt}, 是否满足: {diff <= dt}")
内容的提问来源于stack exchange,提问作者VGB
相关产品推荐
相关产品推荐

