在Pandas 0.20.2中聚合多类型数据时如何获得一致结果?
解决Pandas 0.20.2中聚合混合类型DataFrame时列被丢弃的问题
这确实是Pandas 0.20.2版本里的一个类型兼容小坑——当你同时对timedelta和float类型的列应用多个聚合函数时,只要某列无法适配其中一个函数,Pandas就会悄悄丢弃该列的所有结果。咱们来拆解问题并给出两种可行的解决方案:
问题根源
np.nanmedian原生不支持timedelta64类型的数据。当你同时传入np.nansum和np.nanmedian两个聚合函数时,Pandas尝试对Dur列应用np.nanmedian失败后,直接排除了整个Dur列的聚合结果;而单独使用np.nansum时,timedelta类型可以正常被求和,所以结果符合预期。
解决方案1:为不同列指定专属聚合函数
最稳妥的方式是用字典明确指定每一列需要应用的聚合函数,避免让不兼容的函数去处理timedelta列:
import pandas as pd import numpy as np # 你的示例数据 df=pd.DataFrame(data=pd.date_range('20100201', periods=10, freq='5h3min'),columns=['Start']) df.loc[:,'End']=df.loc[:,'Start']+pd.Timedelta(4,'h') df.loc[:,'Value']=42.0 df.loc[:,'Dur']=df.loc[:,'End']-df.loc[:,'Start'] # 指定列对应的聚合函数 result = df.resample('1D', on='Start').agg({ 'Dur': [np.nansum], # 仅对Dur列应用求和 'Value': [np.nansum, np.nanmedian] # 对Value列应用两个函数 }) print(result)
输出结果会完整包含所有预期列:
Dur Value nansum nansum nanmedian Start 2010-02-01 20:00:00 210.0 42.0 2010-02-02 20:00:00 210.0 42.0
解决方案2:自定义支持timedelta的中位数函数
如果你确实需要对Dur列计算中位数,可以自定义一个函数,先把timedelta转换为数值计算中位数,再转回timedelta类型:
def timedelta_nanmedian(series): # 将timedelta转为总秒数的数值数组 sec_values = series.dt.total_seconds() # 计算中位数 median_sec = np.nanmedian(sec_values) # 转回timedelta类型 return pd.Timedelta(seconds=median_sec) # 应用自定义函数和原生函数 result = df.resample('1D', on='Start').agg({ 'Dur': [np.nansum, timedelta_nanmedian], 'Value': [np.nansum, np.nanmedian] }) print(result)
这个方案会同时得到Dur列的求和与中位数,以及Value列的两个聚合结果,完全满足你的需求。
补充说明
这个列被丢弃的行为在Pandas后续版本(比如0.24+)中已经得到优化——当某列无法应用某个聚合函数时,会在对应位置填充NaN而不是丢弃整列。但如果你必须使用0.20.2版本,上述两种方法可以完美解决问题。
内容的提问来源于stack exchange,提问作者00__00__00
相关产品推荐
相关产品推荐

