在Pandas中结合DateTime使用GroupBy:获取周最小值及对应时间戳
问题:如何在Pandas中按周分组获取最小值及对应时间戳
我从API获取了如下格式的数据(简化示例):
0,1500843600,8872 1,1500807600,18890 2,1500811200,2902 ……
其中第二列为秒级时间戳,第三列为数值。数据涵盖数月内的每小时记录。我希望按周(每周从周一开始)分组,获取每周第三列的最小值,同时返回该最小值对应的具体时间戳。现有代码能正确返回最小值,但无法拿到对应的时间戳,请问如何修改?
现有代码:
import pandas as pd # 补充原代码遗漏的导入 df = pd.DataFrame(columns=['Timestamp', 'Value']) # dic holds the data that I get from my API. for i in range(len(dic)): df.loc[i] = [dic[i][1], dic[i][2]] df['Timestamp'] = pd.to_datetime(df['Timestamp'], unit='s') df.sort_values(by=['Timestamp']) df.set_index(df['Timestamp'], inplace=True) df.groupby([pd.Grouper(key='Timestamp', freq='W-MON')])['Value'].min()
解决方案
刚好我之前处理过类似的时间序列分组需求,给你两种实用的实现方式:
方法1:用idxmin()定位最小值索引,再关联原始数据
groupby.min()只能返回数值,但idxmin()会返回最小值所在行的索引(也就是你要的时间戳),之后我们可以通过这个索引从原始数据里提取对应的时间和数值。
修改后的优化代码:
import pandas as pd # 优化数据加载:直接用API返回的dic构造DataFrame,不用手动循环 df = pd.DataFrame(dic, columns=['idx', 'Timestamp', 'Value']) df = df.drop('idx', axis=1) # 移除没用的第一列 # 转换时间戳并整理索引 df['Timestamp'] = pd.to_datetime(df['Timestamp'], unit='s') df = df.sort_values(by='Timestamp').set_index('Timestamp') # 合并排序+设索引,避免原代码无赋值的无效排序 # 按周分组,获取每个组最小值对应的时间戳索引 weekly_min_idx = df.groupby(pd.Grouper(freq='W-MON'))['Value'].idxmin() # 提取结果并整理格式 weekly_min_result = df.loc[weekly_min_idx].reset_index() weekly_min_result = weekly_min_result.rename(columns={ 'Timestamp': 'Min_Value_Timestamp', 'Value': 'Weekly_Min_Value' }) print(weekly_min_result)
方法2:用agg()自定义聚合逻辑
如果想更简洁,也可以用groupby.agg()直接同时聚合最小值和对应的时间戳,只需要写个小函数处理每个分组:
import pandas as pd # 同样先处理数据加载和时间转换 df = pd.DataFrame(dic, columns=['idx', 'Timestamp', 'Value']) df = df.drop('idx', axis=1) df['Timestamp'] = pd.to_datetime(df['Timestamp'], unit='s') df = df.sort_values(by='Timestamp').set_index('Timestamp') def get_min_with_ts(group): # 找到分组中Value最小的行 min_row = group[group['Value'] == group['Value'].min()] return pd.Series({ 'Weekly_Min_Value': min_row['Value'].values[0], 'Min_Value_Timestamp': min_row.index[0] }) # 分组聚合得到结果 weekly_min_result = df.groupby(pd.Grouper(freq='W-MON')).apply(get_min_with_ts).reset_index() print(weekly_min_result)
额外提两个小优化点
- 原代码里的
df.sort_values(by=['Timestamp'])没有赋值给变量,等于白执行了,一定要记得赋值或者合并到后续操作里 - 数据加载时直接用
pd.DataFrame(dic)比手动循环loc高效得多,数据量大的时候差距会很明显
内容的提问来源于stack exchange,提问作者tinker
相关产品推荐
相关产品推荐

