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

为何Pandas中Sparse DataFrame调用sum()会返回错误结果?

Sparse DataFrame全局求和溢出问题及解决方案

问题描述

在Sparse DataFrame中,对整个数据集调用sum()方法会得到错误结果,但单独对某一列或数据集子集调用sum()却能正常工作。这明显是全局求和时的溢出问题——因为求和结果的类型被设置为Sparse[int8, 0],但为何另外两种场景不会出现该问题?

另外存在一个奇怪的环境差异:在Anaconda终端中运行时,所有场景均返回正确结果,但在PyCharm中会出现错误。

代码复现

import numpy as np
import pandas as pd

# 生成包含二进制变量的普通DataFrame和稀疏DataFrame
# 使用int8以最小化内存占用
df = pd.DataFrame(np.random.randint(low=0, high=2, size=(50_000, 1)))
sdf = df.astype(pd.SparseDtype(dtype='int8', fill_value=0))
print(df.sum(axis=0))
# 输出:0    24954
# dtype: int64

# 为什么这个会返回错误结果,另外两个却正常?
print(sdf.sum(axis=0))
# 输出:0    122
# dtype: Sparse[int8, 0]

# 正常工作
print(sdf[0].sum())
# 输出:24954

# 正常工作
print(sdf[sdf==1].sum())
# 输出:0    24954.0
# dtype: float64

原因分析

  • 全局求和溢出:对整个Sparse DataFrame调用sum(axis=0)时,Pandas默认会尝试保留原稀疏列的int8类型,但int8的取值范围仅为-128~127,而5万条数据的求和结果(约2.5万)远超出这个范围,触发整数溢出,最终得到的122是24954对256(2^8)取模后的结果。
  • 单列求和正常:单独对某一列调用sum()时,Pandas会自动将求和结果的类型提升为更大的整数类型(如int64),避免溢出,因此结果正确。
  • 子集求和正常:sdf[sdf==1]的筛选操作会将原int8稀疏列转换为浮点型稀疏列,求和时以浮点型计算,不会触发int8的溢出限制,因此结果正确。
  • 环境差异原因:Anaconda终端和PyCharm中的Pandas/Numpy版本不同,旧版本的Pandas在Sparse DataFrame全局求和时未做类型提升处理,而新版本修复了该问题,导致不同环境下行为不一致。

安全求和方法(不转密集格式/修改dtype)

  • 方法1:使用apply遍历列求和
    直接对整个Sparse DataFrame调用apply,对每一列单独执行sum操作,写法简洁且结果正确:
    sdf.apply(lambda col: col.sum())
    
  • 方法2:显式指定求和dtype
    在sum()中通过dtype参数强制指定使用更大的整数类型(如int64)进行计算,避免溢出:
    sdf.sum(axis=0, dtype='int64')
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:42:52