Pandas使用loc赋值Total_Count列错位,求按站点卡片计算累计值的代码修改方案
问题根因
你遇到的Total_Count错位问题来自两个错误:
- 筛选得到的子DataFrame
df2保留了原df1的索引,没有重置,循环时用range生成的整数作为loc的索引参数时,匹配的是原df的索引标签,而非当前子df的行位置,导致赋值错位 - 每个卡片(card)分组计算时,没有重置
preSite、preCount变量,上一个卡片的计算缓存值会带入下一个卡片的计算逻辑,导致结果错误
修正后的代码(原循环逻辑适配)
import pandas as pd df1 = pd.DataFrame(columns=['site', 'card', 'date', 'count_record'], data=[['A', 'C1', '12-Oct', 5], ['A', 'C1', '13-Oct', 10], ['A', 'C1', '14-Oct', 18], ['A', 'C1', '15-Oct', 21], ['A', 'C1', '16-Oct', 29], ['B', 'C2', '12-Oct', 11], ['A', 'C2', '13-Oct', 2], ['A', 'C2', '14-Oct', 7], ['A', 'C2', '15-Oct', 13], ['B', 'C2', '16-Oct', 4]]) df_append_temp=[] for pc in df1['card'].unique(): # 筛选排序后重置索引,保证当前子df索引从0连续 df2 = df1[df1['card'] == pc].sort_values(['date']).reset_index(drop=True) # 每个卡片分组单独初始化所有缓存变量,避免跨分组参数污染 total = 0 preSite = '' preCount = 0 for i in range(0, len(df2)): site = df2.iloc[i]['site'] count = df2.iloc[i]['count_record'] if site == preSite: total += (count - preCount) else: total += count preCount = count preSite = site # 索引重置后i与当前子df的索引标签匹配,赋值正常 df2.loc[i, 'Total_Count'] = total df_append_temp.append(df2) df3 = pd.concat(df_append_temp, ignore_index=True) print(df3)
更高效的Pandas原生实现
不需要手动做外层循环,用groupby+自定义累计函数的方案性能更高、逻辑更清晰:
def cal_total(group): total = 0 pre_site = '' pre_count = 0 res = [] for _, row in group.iterrows(): if row['site'] == pre_site: total += row['count_record'] - pre_count else: total += row['count_record'] res.append(total) pre_site = row['site'] pre_count = row['count_record'] group['Total_Count'] = res return group df3 = df1.sort_values(['card', 'date']).groupby('card', group_keys=False).apply(cal_total) print(df3)
内容的提问来源于stack exchange,提问作者Kelvin Lo
相关产品推荐
相关产品推荐

