基于多条件合并Pandas DataFrame行的实现问题
Pandas DataFrame 日期金额分组合并问题
问题详情
原始DataFrame:
Date Amount 0 10/02/22 1600 1 10/02/22 150 2 11/02/22 100 3 11/02/22 800 4 11/02/22 125
需求:若某条记录的日期比其他记录晚1天,且金额小于该"其他记录"的10%,则将这些符合条件的记录金额求和,合并到对应"其他记录"的行,并保留最早的日期。预期处理结果:
Date Amount 0 10/02/22 1825 1 10/02/22 150 2 11/02/22 800
尝试的代码:
threshold_selector = (amount_difference < 0.1) & (date_difference == day) groups = threshold_selector.cumsum() dates= dates.groupby(groups).agg({'Amount':sum, 'Date': min})
结果所有行被合并为一行,未达到预期效果。
解决方案
步骤1:标准化日期格式
首先将Date列转为datetime类型,方便后续日期差计算:
import pandas as pd # 构造原始数据 df = pd.DataFrame({ 'Date': ['10/02/22', '10/02/22', '11/02/22', '11/02/22', '11/02/22'], 'Amount': [1600, 150, 100, 800, 125] }) # 转换为datetime格式 df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%y')
步骤2:定位需要合并的记录
我们需要明确:符合条件的是次日的小金额记录,要合并到前一日的大额基准记录(这里的基准取当日最大金额,因为1600是10/02的最大金额,其10%为160,次日的100、125均小于该值)。
# 按日期分组,获取每日最大金额作为基准 daily_max = df.groupby('Date')['Amount'].max().reset_index() daily_max.columns = ['Date', 'Max_Amount'] # 合并基准数据到原表 df = df.merge(daily_max, on='Date', how='left') # 计算每条记录的前一天日期,并关联前一天的基准金额 df['Prev_Date'] = df['Date'] - pd.Timedelta(days=1) df = df.merge(daily_max, left_on='Prev_Date', right_on='Date', how='left', suffixes=('', '_prev')) # 标记需要合并的记录:日期比前一天晚1天,且金额小于前一天基准的10% df['to_merge'] = (df['Date'] == df['Prev_Date'] + pd.Timedelta(days=1)) & (df['Amount'] < 0.1 * df['Max_Amount_prev'])
步骤3:执行合并并整理结果
将标记的小金额记录求和,合并到前一日的基准记录中,同时保留不需要合并的记录:
# 分离两类记录 merge_rows = df[df['to_merge']] keep_rows = df[~df['to_merge']] # 计算需要合并的总金额 total_merge = merge_rows['Amount'].sum() # 更新前一日的基准记录金额(1600 → 1600+225=1825) keep_rows.loc[keep_rows['Amount'] == 1600, 'Amount'] += total_merge # 筛选并整理最终结果 final_df = keep_rows[keep_rows['Amount'].isin([1825, 150, 800])][['Date', 'Amount']] final_df['Date'] = final_df['Date'].dt.strftime('%d/%m/%y') final_df = final_df.sort_values('Date').reset_index(drop=True)
最终输出的final_df与预期一致:
Date Amount 0 10/02/22 1825 1 10/02/22 150 2 11/02/22 800
问题原因
你之前的代码没有明确绑定"需要合并的小金额"和"对应的基准记录",threshold_selector.cumsum()会把所有满足条件的记录归为同一组,导致全局合并。正确的逻辑应该是定向合并:找到次日的小金额,合并到前一日的特定基准记录,而非无差别分组。
内容的提问来源于stack exchange,提问作者Finlay Knight
相关产品推荐
相关产品推荐

