Pandas DataFrame按不同聚合函数重采样报长度不匹配错误求解
问题背景
现有如下结构的DataFrame,其中Stats列存储每个1秒时间戳对应的统计值类型(包含avg、count、min、max等类型),表结构示例:
| Timestamps | Location | Service | Status Code | Stats | Value |
|---|---|---|---|---|---|
| 1656533176875 | A | s1 | 200 | count | 5000 |
| 1656533176875 | A | s1 | 500 | avg. | 3000 |
| .... | .... | .... | .... | ... | ... |
| 1656533176878 | B | s2 | 504 | max. | 6000 |
需求为对该DataFrame按用户自定义时间间隔(例如5分钟)执行重采样,聚合对应时间区间内的数值。聚合规则为按Stats列类型匹配聚合函数:
Stats值为avg时,对区间内数值求均值Stats值为count时,对区间内数值求和
其余统计类型同理匹配对应聚合逻辑,分组维度需包含location、service、status code。
现有实现代码运行后触发报错:ValueError: Length of values (1) does not match the length of index (10),无法得到预期结果,原有代码如下:
#sample dataframe rng = pd.date_range('2022-06-01', periods=10, freq='T') np.random.seed(10) l = ['A', 'B', 'C', 'D'] k = ['avg', 'max', 'min', 'count', 'median', 'std'] m = ['s1', 's2', 's3'] j = [200, 400, 404, 500] df = pd.DataFrame( {'date_time': rng, 'location': random.choices(l, k=10), 'service': random.choices(m, k=10), 'status': random.choices(j, k=10), 'stat': random.choices(k, k=10), 'value': np.random.randint(100, 900, size=10) } ) df.sort_values(by=df.columns.to_list()) print(df) interval =5 resampled_df = df.assign( n_count=np.where(df['stat'] == 'count'), n_median=np.where(df['stat'] == 'median'), n_max=np.where(df['stat'] == 'max'), n_min=np.where(df['stat'] == 'min'), n_avg=np.where(df['stat'] == 'avg'), n_std=np.where(df['stat'] == 'std'), ).groupby(['date_time', 'location', 'services', 'status_code', 'stat']) \ .resample('{}min'.format(interval), on='date_time') \ .value \ .agg({'n_count': sum, 'n_avg': np.mean, 'n_max': max, 'n_min': min, 'n_std': np.std, 'n_median': np.median}) print(resampled_df)
错误原因
原有代码存在4个核心问题:
np.where用法错误:仅传入了判断条件,未指定条件成立/不成立时的填充值,返回结果长度和原DataFrame索引长度不匹配,直接触发长度报错- 列名引用错误:分组时使用了不存在的列名
services、status_code,原数据对应列名为service、status - 逻辑设计冗余:不需要为每个统计类型单独创建辅助列,将
stat放入分组键后再做多列聚合的逻辑完全不符合需求 - 排序操作无效:
df.sort_values()未接收返回值也未设置inplace=True,排序操作实际未生效
修正方案
首先定义统计类型和聚合函数的映射关系,先按业务维度分组,再在每个分组内做时间重采样,最后按统计类型匹配聚合规则即可,修正后可运行代码如下:
import pandas as pd import numpy as np import random # 构造示例数据 rng = pd.date_range('2022-06-01', periods=10, freq='T') np.random.seed(10) l = ['A', 'B', 'C', 'D'] k = ['avg', 'max', 'min', 'count', 'median', 'std'] m = ['s1', 's2', 's3'] j = [200, 400, 404, 500] df = pd.DataFrame( {'date_time': rng, 'location': random.choices(l, k=10), 'service': random.choices(m, k=10), 'status': random.choices(j, k=10), 'stat': random.choices(k, k=10), 'value': np.random.randint(100, 900, size=10) } ) # 若源数据stat带末尾点号,可打开下一行做统一清洗 # df['stat'] = df['stat'].str.rstrip('.') interval = 5 # 定义统计类型对应的聚合函数 agg_map = { 'count': 'sum', 'avg': 'mean', 'max': 'max', 'min': 'min', 'median': 'median', 'std': 'std' } resampled_df = ( df # 先按三个业务维度分组,每个维度组内单独做时间重采样 .groupby(['location', 'service', 'status']) # 对date_time列做指定间隔重采样 .resample(f'{interval}min', on='date_time') # 每个时间窗口内,按stat类型分组,对value应用对应聚合函数 .apply(lambda x: x.groupby('stat')['value'].agg(agg_map)) # 重置索引得到规整结果 .reset_index() ) print(resampled_df)
结果说明
运行后输出的结果集包含location/service/status/date_time四个维度列,以及各统计类型对应的聚合后数值列,完全匹配需求:同一时间窗口、同一业务维度下,不同统计类型的值均按规则完成聚合,无跨维度、跨统计类型的计算错误。
内容的提问来源于stack exchange,提问作者sherin_a27
相关产品推荐
相关产品推荐

