You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算客户近6个月营业额出现负值的原因排查求助

问题根源:整数溢出(Int32范围超限)

首先,你看到的负值尤其是 -2.147484e+09 是Int32类型的最小值(也就是 -2^31),这说明你的求和结果超过了Int32的最大值(2^31-1 = 2147483647),导致了整数溢出,数值被“绕回”成了负数。这是代码里最核心的问题,咱们一步步拆解修复:

1. 修复类型溢出问题

在你的代码中,滚动求和后调用了 .astype(int),而Pandas在很多环境下默认的int是Int32类型。当单个客户的滚动销售额总和超过2147483647时,就会触发溢出,得到错误的负值。

修改方式:把 astype(int) 替换为 astype(np.int64) 或者 astype('int64'),Int64的范围足够大(从 -9223372036854775808 到 9223372036854775807),完全能覆盖你的业务数据量。

修改后的代码片段:

# 2nd pass: use a sliding window of 180 days to sum
df1 = df1.rolling(180, min_periods=0).sum().astype(np.int64)  # 这里改了两个地方:窗口从90→180,类型从int→int64

2. 修正滚动窗口的天数(匹配需求)

你的需求是计算近6个月营业额,但代码里用的是 rolling(90, ...)(90天),这和需求不符,所以顺便把窗口大小改成180天(近似6个月的天数)。

3. 修复DataFrame排序的问题

你调用了 df.sort_values(['customerId', 'fromDate'], ignore_index=True) 但没有把结果赋值回df,这意味着原DataFrame并没有被排序!滚动窗口的计算依赖于时间序列的有序性,所以必须把排序后的结果保存下来:

修改成:

# Ensure your dataframe is sorted by fromDate for rolling window
df = df.sort_values(['customerId', 'fromDate'], ignore_index=True)  # 加上赋值

完整修复后的代码

import pandas as pd
import numpy as np
import multiprocessing as mp
import time

def sum_sales(customer, df):
    # 1st pass: sum sales of same days, reduce the row numbers
    df1 = df.groupby('fromDate')['sales'].sum()
    # Generate all missing dates
    df1 = df1.reindex(pd.date_range(df1.index.min(), df1.index.max(), freq='D'), fill_value=0)
    # 2nd pass: use a sliding window of 180 days to sum
    df1 = df1.rolling(180, min_periods=0).sum().astype(np.int64)
    # Restore original index for the group
    df1 = df1.reindex(df['fromDate']).reset_index(drop=True).to_frame().set_index(df.index)
    return df1

if __name__ == '__main__':
    # Setup a minimal reproducible example
    N = 3_000_000
    D = pd.to_datetime('2021-1-1')
    rng = np.random.default_rng(2022)
    dti = D + pd.to_timedelta(rng.integers(0, 365*2, N), unit='D')
    cust = rng.integers(0, 75000, N)
    sales = rng.integers(1, 200, N)
    df = pd.DataFrame({'customerId': cust, 'fromDate': dti, 'sales': sales})
    # Ensure your dataframe is sorted by fromDate for rolling window
    df = df.sort_values(['customerId', 'fromDate'], ignore_index=True)
    start = time.time()
    with mp.Pool(mp.cpu_count() - 1) as p:
        results = p.starmap(sum_sales, df.groupby('customerId'))
    df['total_sales'] = pd.concat(results)
    end = time.time()
    print(f"Elapsed time: {end - start:.2f} seconds")
    # 验证结果是否正常
    print(df['total_sales'].describe())

验证修复效果

运行修复后的代码后,df['total_sales']的统计结果应该全部为正值,不会再出现负数,而且数值符合近6个月销售额的求和逻辑。

内容的提问来源于stack exchange,提问作者Test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 00:57:33