如何用Pandas计算每日上午、下午时段sig的平均值?
问题描述
现有如下Pandas DataFrame:
gpi_data[['sig','hourtime']] Out[28]: sig hourtime datetime_doy 2007-01-02 -8.963545 2007-01-02 09:20:11.249998 2007-01-03 -8.671357 2007-01-03 10:39:31.874991 2007-01-03 -8.996480 2007-01-03 20:22:59.999006 2007-01-04 -8.835958 2007-01-04 10:18:56.249024 2007-01-05 -8.785034 2007-01-05 21:21:39.374002 ... ... 2019-12-30 -8.529724 2019-12-30 20:23:01.874996 2019-12-30 -8.563781 2019-12-30 20:48:28.125016 2019-12-30 -8.504211 2019-12-30 21:23:44.999996 2019-12-31 -8.460620 2019-12-31 09:39:31.873999 2019-12-31 -8.230092 2019-12-31 10:18:58.125014 [7983 rows x 2 columns]
需要基于hourtime字段,按每日的**上午(10:00左右)和下午(22:00左右)**时段计算sig的平均值,规则如下:
- 当日某时段无数据时,用
np.nan填充; - 某时段有多条数据时,取该时段所有
sig的平均值; - 需覆盖整个时间范围的所有日期,哪怕当日无任何数据(如2007-01-01),也要生成上午、下午两条记录,均填充
np.nan。
期望输出示例(hourtime可规整为10:00:00/22:00:00):
gpi_data[['sig','hourtime']] Out[28]: sig hourtime datetime_doy 2007-01-01 NaN 2007-01-01 10:00:00 2007-01-01 NaN 2007-01-01 22:00:00 2007-01-02 -8.963545 2007-01-02 10:00:00 2007-01-02 NaN 2007-01-02 22:00:00 2007-01-03 -8.671357 2007-01-03 10:00:00 2007-01-03 -8.996480 2007-01-03 22:00:00 2007-01-04 -8.835958 2007-01-04 10:00:00 2007-01-04 NaN 2007-01-04 22:00:00 2007-01-05 NaN 2007-01-05 10:00:00 2007-01-05 -8.785034 2007-01-05 22:00:00 ... ... 2019-12-30 -8.532572 2019-12-30 22:00:00 2019-12-31 -8.345356 2019-12-31 10:00:00 2019-12-31 NaN 2019-12-31 22:00:00
解决方案
可以通过以下步骤实现需求:
1. 导入依赖库
import pandas as pd import numpy as np
2. 标记数据所属时段
从hourtime中提取日期,并根据时间范围判断所属时段:
# 提取hourtime的日期部分 gpi_data['date'] = gpi_data['hourtime'].dt.date # 定义时段:上午为9:00-11:00,下午为20:00-24:00 gpi_data['period'] = np.where( (gpi_data['hourtime'].dt.hour >=9) & (gpi_data['hourtime'].dt.hour <11), 'morning', np.where( (gpi_data['hourtime'].dt.hour >=20) & (gpi_data['hourtime'].dt.hour <24), 'afternoon', np.nan ) ) # 过滤掉不属于目标时段的数据 gpi_data = gpi_data.dropna(subset=['period'])
3. 按日期+时段聚合平均值
# 分组计算每个日期、时段的sig均值 agg_data = gpi_data.groupby(['date', 'period'])['sig'].mean().reset_index()
4. 生成完整的日期-时段组合
确保覆盖时间范围内的所有日期,包括无数据的日期:
# 获取数据的时间边界 min_date = gpi_data['date'].min() max_date = gpi_data['date'].max() # 生成该范围内的所有日期 all_dates = pd.date_range(start=min_date, end=max_date).date # 定义两个时段 periods = ['morning', 'afternoon'] # 生成日期和时段的笛卡尔积,得到完整的索引组合 full_index = pd.MultiIndex.from_product([all_dates, periods], names=['date', 'period']) # 将聚合数据转为MultiIndex,与完整索引对齐 agg_data = agg_data.set_index(['date', 'period']) full_data = agg_data.reindex(full_index).reset_index()
5. 规整输出格式
生成规整的hourtime字段,并设置目标索引:
# 根据时段生成10:00或22:00的标准时间 full_data['hourtime'] = pd.to_datetime( full_data['date'].astype(str) + ' ' + np.where(full_data['period'] == 'morning', '10:00:00', '22:00:00') ) # 设置datetime_doy为索引 full_data = full_data.set_index(pd.to_datetime(full_data['date'])) full_data.index.name = 'datetime_doy' # 保留最终需要的列 result = full_data[['sig', 'hourtime']]
最终result即为符合要求的输出DataFrame。
内容的提问来源于stack exchange,提问作者Xu Shan
相关产品推荐
相关产品推荐

