Python Pandas聚合DataFrame:求和全为NaN时返回NaN而非0
Pandas分组求和:全NaN列返回NaN而非0
问题背景
我在Python Pandas中有如下DataFrame:
输入数据:
import numpy as np import pandas as pd df = pd.DataFrame({ 'id' : [999, 999, 999, 185, 185, 185, 999, 999, 999], 'target' : [1, 1, 1, 0, 0, 0, 1, 1, 1], 'event': ['2023-01-01', '2023-01-01', '2023-02-03', '2023-01-01', '2023-01-02', '2023-01-03', '2023-01-01', '2023-01-02', '2023-01-03'], 'survey': ['2023-02-02', '2023-02-02', '2023-02-02', '2023-03-10', '2023-03-10', '2023-03-10', '2023-04-22', '2023-04-22', '2023-04-22'], 'event1': [1, 6, 11, 16, np.nan, 22, 74, 109, 52], 'event2': [2, 7, np.nan, 17, 22, np.nan, np.nan, 10, 5], 'event3': [3, 8, 13, 18, 23, np.nan, 2, np.nan, 99], 'event4': [4, 9, np.nan, np.nan, np.nan, 11, 8, np.nan, np.nan], 'event5': [np.nan, np.nan, 15, 20, 25, 1, 1, 3, np.nan] })
观察数据可知,当id=999且event='2023-01-01'时,event5列存在2个NaN值。
需求:
按id、target、survey、event分组,对event1至event5列求和;当分组内某列全为NaN时,求和结果返回NaN而非默认的0。
现有代码执行后,全NaN列的求和结果为0,不符合需求:
column_names = df.columns df = df.groupby(["id","target", "survey", "event"]).agg({col: 'sum' for col in column_names if col not in ["id","target", "survey", "event"]}) df.reset_index(inplace = True)
解决方案
方法1:利用sum的min_count参数
Pandas的sum方法内置min_count参数,可指定返回有效求和结果所需的最小非NaN值数量。设置min_count=1时,若分组内该列无有效数值(全NaN),则返回NaN。
修改后的代码:
# 筛选需要聚合的列 agg_columns = [col for col in df.columns if col not in ["id", "target", "survey", "event"]] # 分组聚合,为每个列指定带min_count的sum逻辑 df_result = df.groupby(["id", "target", "survey", "event"]).agg( {col: lambda x: x.sum(min_count=1) for col in agg_columns} ).reset_index()
方法2:自定义聚合函数
如果需要更灵活的判断逻辑,可以自定义函数,先检查分组内是否全为NaN,再决定返回值:
import numpy as np def sum_keep_nan(col): # 检查列是否全为NaN if col.isna().all(): return np.nan # 否则返回求和结果 return col.sum() agg_columns = [col for col in df.columns if col not in ["id", "target", "survey", "event"]] df_result = df.groupby(["id", "target", "survey", "event"]).agg( {col: sum_keep_nan for col in agg_columns} ).reset_index()
效果验证
以id=999、survey='2023-02-02'、event='2023-01-01'的分组为例:
event5列有2个NaN和1个有效值15,求和结果为15(符合预期);- 若某分组内某列全为NaN,求和结果会返回NaN而非0。
内容的提问来源于stack exchange,提问作者dingaro
相关产品推荐
相关产品推荐

