如何在时间序列Pandas列中按季度统计非零元素数量
解决时间序列DataFrame按季度统计非零元素数量的问题
我来帮你搞定这个需求!从你的示例数据能看出来,你需要把每3个时间点划分为一个季度,在每个季度的最后一行新增列C,统计该季度内A列的非零元素数量。之前用pd.rolling(3).count()没达到预期,是因为这个方法统计的是窗口内非缺失值的数量,而非你需要的非零元素数量,咱们换个思路来实现:
方法一:按固定行数(每3行)分组统计
如果你的时间序列是严格按每3行对应一个季度的规则排列的,可以用这种方法:
步骤说明
- 给每行添加分组标识,把连续3行归为一组;
- 计算每个分组内A列的非零元素数量;
- 将统计结果赋值到对应分组的最后一行的
C列; - 清理临时的分组列。
完整代码
import pandas as pd import numpy as np # 先模拟你的示例数据 data = { 'time': ['time1', 'time2', 'time3', 'time4', 'time5', 'time6', 'time7', 'time8', 'time9', 'time10', 'time11', 'time12'], 'A': [5, 0, 3, 4, 9, 4, 2, 0, 0, 3, 4, 7], 'B': [np.nan]*12 # 示例中B列是空值,这里用NaN模拟 } df = pd.DataFrame(data).set_index('time') # 1. 创建分组标识:每3行一组 df['group'] = np.arange(len(df)) // 3 # 2. 计算每个分组内A列的非零元素数量 group_nonzero_counts = df.groupby('group')['A'].apply(lambda x: (x != 0).sum()) # 3. 将统计结果赋值到每个分组的最后一行的C列 df.loc[df.groupby('group').tail(1).index, 'C'] = group_nonzero_counts.values # 4. 删除临时的group列 df.drop('group', axis=1, inplace=True) # 查看结果 print(df)
输出结果
A B C time time1 5 NaN NaN time2 0 NaN NaN time3 3 NaN 2.0 time4 4 NaN NaN time5 9 NaN NaN time6 4 NaN 3.0 time7 2 NaN NaN time8 0 NaN NaN time9 0 NaN 1.0 time10 3 NaN NaN time11 4 NaN NaN time12 7 NaN 3.0
方法二:按实际时间季度分组(更严谨)
如果你的time列是标准的日期时间类型(比如datetime),推荐用这种方法,它会自动按自然季度(1-3月、4-6月等)分组,比固定行数更准确:
完整代码
import pandas as pd import numpy as np # 模拟带真实日期的时间序列数据 data = { 'time': pd.date_range(start='2023-01-01', periods=12, freq='M'), # 每月最后一天 'A': [5, 0, 3, 4, 9, 4, 2, 0, 0, 3, 4, 7], 'B': [np.nan]*12 } df = pd.DataFrame(data).set_index('time') # 按季度分组,计算每组A列的非零元素数量 quarter_counts = df.groupby(pd.Grouper(freq='Q'))['A'].apply(lambda x: (x != 0).sum()) # 将统计结果赋值到每个季度最后一个月的C列 df.loc[quarter_counts.index, 'C'] = quarter_counts.values # 查看结果 print(df)
关键说明
pd.Grouper(freq='Q')会自动将数据按自然季度分组,Q代表季度频率;- 如果需要同时统计A和B列的非零元素,只需要把
['A']改成['A', 'B'],然后用(df[['A','B']] != 0).sum(axis=1).groupby(...)调整统计逻辑即可。
内容的提问来源于stack exchange,提问作者Chuck
相关产品推荐
相关产品推荐

