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

如何用Pandas的Pivot与Groupby生成月均小时数据

问题解决:按小时分组计算各月份对应小时的平均值

问题描述

现有一个以datetime index为索引的DataFrame(仅含单列数据),需要将其重塑为以小时为索引、月份(1-12)为列的结构,计算每个月对应小时的平均值,最终得到各月份的小时均值数据。当前代码仅能算出全年小时平均值,无法生成分月份的列,需修正实现方法。

用户尝试代码

尝试代码1

import pandas as pd
import numpy as np

dti = pd.date_range("2018-01-01", periods=8760, freq="H")

np.random.seed(seed=1111)
data = np.random.randint(1, high=100, size=len(dti))
data1 = np.random.randint(1, high=100, size=len(dti))
data2 = np.random.randint(1, high=100, size=len(dti))
data3 = np.random.randint(1, high=100, size=len(dti))

df = pd.DataFrame({'date': dti, 'data': data, 'data1': data1, 'data2': data2, 'data3': data3 })
df = df.set_index('date')

df1 = df[['data']]
pd.pivot(df1,index=df1.index.hour,columns=df1.index.month)
df1 = df1.groupby(df1.index.hour).mean()
print(df1)

尝试代码2

import pandas as pd
import numpy as np

dti = pd.date_range("2018-01-01", periods=8760, freq="H")

np.random.seed(seed=1111)
data1 = np.random.randint(1, high=100, size=len(dti))
data2 = np.random.randint(1, high=100, size=len(dti))
data3 = np.random.randint(1, high=100, size=len(dti))
data4 = np.random.randint(1, high=100, size=len(dti))

df = pd.DataFrame({'date': dti, 'data1': data1, 'data2': data2, 'data3': data3, 'data4': data4 })
df = df.set_index('date')

df1 = df[['data1']]
#pd.pivot(df1,index=df1.index.hour,columns=df1.index.month, values=df1[["data1"]])
df1 = df1.groupby(df1.index.hour).mean()
#print(df1)

当前输出

data1
date           
0     47.873973
1     49.454795
2     50.810959
3     48.726027
4     49.654795
5     49.745205
6     50.342466
7     47.753425
8     46.515068
9     49.364384
10    53.583562
11    49.983562
12    50.178082
13    51.049315
14    49.813699
15    51.032877
16    49.501370
17    49.641096
18    49.463014
19    48.504110
20    49.621918
21    51.060274
22    48.736986
23    50.139726

正确实现方案

核心逻辑是同时按小时和月份分组计算均值,再通过unstack将月份维度转为列,最终得到目标结构。

完整代码

import pandas as pd
import numpy as np

# 生成测试数据(保持与原代码一致的随机种子)
dti = pd.date_range("2018-01-01", periods=8760, freq="H")
np.random.seed(seed=1111)
data = np.random.randint(1, high=100, size=len(dti))
# 构建datetime索引的单列DataFrame
df = pd.DataFrame({'data': data}, index=dti)

# 关键步骤:按小时+月份分组求均值,将月份转为列
result = df.groupby([df.index.hour, df.index.month])['data'].mean().unstack(level=1)

# 可选:给列重命名为更直观的格式
result.columns = [f'月份{month}' for month in result.columns]

print(result)

代码说明

  1. 分组逻辑:groupby([df.index.hour, df.index.month]) 同时按小时和月份分组,确保计算的是每个月内每个小时的平均值,而非全年小时均值。
  2. 重塑结构:.unstack(level=1) 将分组后的月份(第二个分组维度)从多层索引转为列,直接得到以小时为行、月份为列的表格。
  3. 列名优化:通过列表推导式将列名从数字改为月份1、月份2这类更易读的格式。

预期输出示例

月份1       月份2       月份3       月份4       月份5       月份6       月份7       月份8       月份9       月份10      月份11      月份12
0  48.354839  45.535714  49.096774  48.583333  47.935484  47.250000  48.096774  47.387097  47.083333  48.225806  47.516129  48.903226
1  52.129032  48.714286  49.225806  48.750000  49.000000  49.083333  48.000000  48.225806  49.333333  49.516129  47.096774  50.000000
2  52.096774  51.214286  52.032258  50.583333  50.129032  49.916667  50.000000  50.290323  50.166667  50.000000  49.032258  49.000000
...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:04:57