Pandas时间序列分组:实现基于数据起始时间的24小时周期分组

Pandas时间序列分组:实现基于数据起始时间的24小时周期分组

本教程详细探讨了如何在Pandas中利用pd.Grouper实现基于数据首次时间戳的24小时周期分组,而非默认的日历日分组。通过设置origin=’start’参数,用户可以精确控制分组的起始点,从而满足跨日期但保持固定时间间隔的分析需求,避免了freq=’24H’默认行为的常见误解。

引言:理解时间序列的24小时分组挑战

在数据分析中,我们经常需要对时间序列数据进行周期性分组,例如按小时、天、周或月进行聚合。pandas库提供了强大的工具来处理这类任务,其中pd.grouper是进行时间序列分组的核心功能之一。然而,在使用pd.grouper配合freq=’24h’进行24小时分组时,一个常见的误解是它会从数据中的第一个时间戳开始,每隔24小时创建一个分组。实际上,pd.grouper的默认行为是根据日历日(即从每个日期的午夜00:00:00开始)进行分组,即使指定的频率是’24h’。

例如,如果数据从2023-11-18 17:00:00开始,默认的24H分组会从2023-11-18 00:00:00开始计算,导致第一个分组可能只包含2023-11-18 17:00:00到2023-11-18 23:59:59的数据,而不是从2023-11-18 17:00:00到2023-11-19 16:59:59的完整24小时周期。本教程的目标正是解决这一问题,指导用户如何实现灵活的、以数据首个时间戳为起点的24小时周期分组。

pd.Grouper与origin参数详解

pd.Grouper是Pandas中用于对DataFrame或Series进行时间序列分组的关键对象。它允许用户通过指定键(通常是时间戳列)和频率来定义分组规则。

  • key参数:指定DataFrame中作为时间索引或包含时间戳的列名。
  • freq参数:定义分组的时间间隔,例如’H’(小时)、’D’(天)、’W’(周)、’M’(月)或’24H’(24小时)。
  • origin参数:这是实现自定义分组起始点的核心参数。它决定了分组区间的起始锚点。origin参数有多个可选值,其中最常用且与本文主题相关的包括:
    • ‘start_day’ (默认值):这是pd.Grouper在没有明确指定origin时的默认行为。它将分组的起始点锚定到每个日期的午夜(00:00:00),无论数据中的第一个时间戳是几点。
    • ‘start’:此选项会将分组的起始点锚定到数据集中第一个时间戳的精确时间。例如,如果数据的第一条记录是2023-11-18 17:13:12,那么所有的24小时分组都将从该时间点的小时(即17点)开始计算,形成[17:00, 16:59)的24小时周期。
    • 其他origin选项,如’start_time’(锚定到第一个时间戳的时间部分,但日期部分仍按日历日)、’end’、’end_day’等,提供了更多灵活性,但对于本教程的24小时周期需求,’start’是首选。

实践示例:实现自定义24小时分组

为了更好地说明origin参数的作用,我们将通过一个具体的例子来演示。

首先,我们创建一个模拟的DataFrame,其中包含每小时生成的时间戳和一些测量值。

import pandas as pd import numpy as np  # 创建一个从2023-12-01 17:00到2023-12-02 17:00的日期时间范围 dti = pd.date_range('2023-12-01 17:00', '2023-12-02 17:00', freq='1H') # 创建一个DataFrame df = pd.DataFrame({'created_at': dti, 'moisture': np.random.randint(500, 550, len(dti))})  print("原始DataFrame:") print(df.head()) print("...") print(df.tail())

输出的DataFrame将包含从2023-12-01 17:00:00开始的数据点。

原始DataFrame:            created_at  moisture 0 2023-12-01 17:00:00       513 1 2023-12-01 18:00:00       520 2 2023-12-01 19:00:00       535 3 2023-12-01 20:00:00       533 4 2023-12-01 21:00:00       516 ...             created_at  moisture 20 2023-12-02 13:00:00       532 21 2023-12-02 14:00:00       520 22 2023-12-02 15:00:00       514 23 2023-12-02 16:00:00       528 24 2023-12-02 17:00:00       545

1. 默认分组行为 (origin=’start_day’)

首先,我们演示不指定origin参数(即使用默认值’start_day’)时pd.Grouper的行为。

print("n--- 默认分组 (origin='start_day') ---") df_groupby_default = df.groupby(pd.Grouper(key='created_at', freq='24H')).size() print(df_groupby_default)

输出结果:

--- 默认分组 (origin='start_day') --- created_at 2023-12-01     7  # 从 2023-12-01 00:00:00 到 2023-12-01 23:59:59 2023-12-02    18  # 从 2023-12-02 00:00:00 到 2023-12-02 23:59:59 Freq: 24H, dtype: int64

从输出可以看出,第一个分组的起始时间是2023-12-01 00:00:00,它包含了当天所有数据(即从17:00:00到23:00:00的7个数据点)。第二个分组从2023-12-02 00:00:00开始,包含了2023-12-02当天的数据。这显然不是我们期望的从数据起始时间开始的24小时周期。

2. 自定义起始点的分组 (origin=’start’)

现在,我们使用origin=’start’参数来修正分组行为,使其从DataFrame的第一个时间戳开始计算24小时周期。

Pandas时间序列分组:实现基于数据起始时间的24小时周期分组

Poe

Quora旗下的对话机器人聚合工具

Pandas时间序列分组:实现基于数据起始时间的24小时周期分组289

查看详情 Pandas时间序列分组:实现基于数据起始时间的24小时周期分组

print("n--- 自定义分组 (origin='start') ---") df_groupby_custom = df.groupby(pd.Grouper(key='created_at', freq='24H', origin='start')).size() print(df_groupby_custom)

输出结果:

--- 自定义分组 (origin='start') --- created_at 2023-12-01 17:00:00    24  # 从 2023-12-01 17:00:00 到 2023-12-02 16:59:59 2023-12-02 17:00:00     1  # 从 2023-12-02 17:00:00 到 2023-12-03 16:59:59 Freq: 24H, dtype: int64

通过设置origin=’start’,我们可以看到分组的起始时间变成了2023-12-01 17:00:00,这与我们数据中的第一个时间戳完全一致。第一个分组包含了从2023-12-01 17:00:00到2023-12-02 16:59:59共24个数据点,完美地形成了我们期望的24小时周期。第二个分组从2023-12-02 17:00:00开始,包含了剩余的1个数据点。

3. resample方法的等效应用

除了groupby结合pd.Grouper,Pandas的resample方法也提供了类似的功能,并且同样支持origin参数。resample通常用于时间序列的重采样和聚合。

print("n--- 使用 resample 方法 (origin='start') ---") df_resample_custom = df.resample(rule='24H', on='created_at', origin='start').size() print(df_resample_custom)

输出结果:

--- 使用 resample 方法 (origin='start') --- created_at 2023-12-01 17:00:00    24 2023-12-02 17:00:00     1 Freq: 24H, dtype: int64

可以看到,resample方法通过设置origin=’start’也实现了与pd.Grouper相同的结果。在实际应用中,resample通常更简洁,尤其当时间列已经是DataFrame的索引时。

注意事项

在使用pd.Grouper或resample进行时间序列分组时,有几个关键点需要注意:

  • 时间列的数据类型:确保用于分组的时间列是Pandas的datetime类型。如果不是,需要使用pd.to_datetime()进行转换。
  • origin参数的选择:根据具体的分析需求选择合适的origin值。如果需要传统的日历日分组(例如,每天的销售额),则’start_day’(或不指定origin)是合适的。如果需要从数据首次记录的时间点开始计算固定周期,那么’start’是正确的选择。
  • 时区处理:如果你的时间序列数据包含时区信息,origin参数也会根据时区进行计算。在处理跨时区或具有本地化时间戳的数据时,应特别注意时区转换和统一。
  • 频率与偏移:origin参数不仅适用于’24H’,也适用于其他频率(如’12H’、’W’、’M’等)。其行为会根据频率类型和origin值的组合而有所不同,建议在不确定时进行小规模测试。
  • 聚合操作:groupby或resample后,通常会跟一个聚合函数(如sum()、mean()、count()等)来计算每个分组的统计量。本教程中使用了.size()来演示分组的元素数量。

总结

在Pandas中对时间序列数据进行24小时周期分组时,理解pd.Grouper(或resample)的origin参数至关重要。默认情况下,freq=’24H’会基于日历日(午夜)进行分组,这可能不符合从数据起始点开始计算固定24小时周期的需求。通过明确设置origin=’start’,我们可以精确地将分组的起始点锚定到数据集中的第一个时间戳,从而实现真正意义上的、日期无关的24小时周期分组。掌握这一技巧,将大大提升您在处理复杂时间序列数据时的灵活性和准确性。

工具 ai 聚合函数 pandas 数据类型 count 对象 数据分析

上一篇
下一篇