【问题标题】:pandas groupby half hourly timeseries datapandas groupby 半小时时间序列数据
【发布时间】:2021-12-02 02:26:44
【问题描述】:

我有一个半小时的电力数据时间序列,如下所示:

                Date_Time  Metered Electricity (MWh)
0     2016-03-27 00:00:00                   8.644511
1     2016-03-27 00:30:00                   6.808402
2     2016-03-27 01:00:00                   6.507068
3     2016-03-27 01:30:00                   5.271631
4     2016-03-27 02:00:00                   2.313497
...                   ...                        ...
58122 2019-06-30 11:30:00                   8.051935
58123 2019-06-30 12:00:00                   3.520226
58124 2019-06-30 12:30:00                   5.093964

我想将所有数据点平均为每半小时时间步长的平均值,最终我可以创建一个图表来显示全天的平均发电量。

我已经设法使用 groupby 对每小时数据执行此操作,效果很好:

mean_hourly = energy_2018.groupby(energy_2018["Date_Time"].dt.hour).mean()

如果我无法计算出如何每半小时进行一次分组,我可以使用它,但这意味着我错过了所有数据的一半。知道如何每半小时使用一次 groupby 以便我可以使用所有数据吗?

谢谢!

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    您可以按小时和分钟进行分组和分组。由于您仅以半小时为间隔记录数据,因此您每小时和每 30 分钟获得一个不同的组。

    import pandas as pd
    df = pd.DataFrame({
        'time': ['2016-03-27 00:00:00',
                '2016-03-27 00:00:00',                  
                '2016-03-27 00:30:00',                  
                '2016-03-27 01:00:00',                   
                '2016-03-27 01:30:00',                 
                '2019-06-30 11:30:00',                   
                '2019-06-30 12:00:00',                 
                '2019-06-30 12:30:00'],
        'electricity': [8.644511,
                        6.808402,
                        6.507068,
                        5.271631,
                        2.313497,
                        8.051935,
                        3.520226,
                        5.093964]
    })
    
    df['time'] = pd.to_datetime(df['time'])
    df['minutes'] = df['time'].apply(lambda x: x.minute)
    df['hour'] = df['time'].apply(lambda x: x.hour)
    df.groupby(['hour', 'minutes']).mean()
    

    输出:

    编辑:

    正如 Quang Hoang 的评论中所指出的,获取小时和分钟的更好方法是

    df['minutes'] = df['time'].dt.minute
    df['hour'] = df['time'].dt.hour
    

    最好使用标准库中的现有解决方案,以提高可读性和性能。另一方面,lambda expressions 确实提供了一些灵活性,并且有时非常有用。如果您有兴趣,可以在这里阅读更多内容:

    Why are Python lambdas useful?

    https://www.code-learner.com/advantages-and-disadvantages-of-lambda-expressions-in-python-and-their-usage-scenarios/

    【讨论】:

    • df['time'].dt.hour 和 dt['time'].dt.minute` 是获取小时和分钟的更好方法。
    • 感谢@DataFace,我从来没有真正看到过 lambda 函数的实际作用,也真正理解了发生了什么,但现在我明白了!但无论如何,谢谢你们,这正是我想要的。
    • 似乎有 3 个答案都适用于 OP 提供的输入数据。对于在时间之间有中断的数据,如果您需要那些“中间”间隙,那么@Wilian resample 方法是最好的;如果您不需要灵活性并可能修改您的 groupby 列(即小时、分钟很好,但如果 groupby 小时、分钟、秒怎么办,那么您必须创建额外的列以获取额外的详细信息或所需的时间分辨率所以这不太灵活)但它的工作原理是 Wilian 的解决方案。如果您希望 y 时间段的 x 单位具有广泛的灵活性,那么 pd.Grouper 是最灵活的。
    • 在我的帖子之后,我了解到 lambda 表达式是相当有争议的,但我想指出,如果你的数据没有按固定间隔记录得到 2 half,你可以使用df['time'].apply(lambda x: 0 if x.minute < 30 else 1)每小时组。我当然同意重采样方法更加通用和清晰。
    【解决方案2】:
    df = pd.read_excel('test.xlsx')
    print(df)
    

    输出:

                Date_Time  Metered Electricity (MWh)
    0 2016-03-27 00:00:00                          1
    1 2016-03-27 00:29:00                          2
    2 2016-03-27 00:59:00                          3
    3 2016-03-27 00:57:00                          4
    4 2016-03-27 02:00:00                          5
    

    然后这样做:

    df.set_index('Date_Time',inplace=True)
    df = df.resample("30T").mean().reset_index()
    print(df)
    

    输出:

                Date_Time  Metered Electricity (MWh)
    0 2016-03-27 00:00:00                        1.5
    1 2016-03-27 00:30:00                        3.5
    2 2016-03-27 01:00:00                        NaN
    3 2016-03-27 01:30:00                        NaN
    4 2016-03-27 02:00:00                        5.0
    

    编辑

    或者只是这个:

    df = df.set_index('Date_Time').resample("30T").mean().reset_index()
    

    【讨论】:

    • 啊,我明白你在做什么,但我的数据已经是半小时一次,所以我不需要重新采样。我只想要整个数据集中每半小时时间的平均值。
    • df['平均 30 分钟'] = df.groupby(pd.Grouper(key='Date_Time', freq='30min')).transform('mean')
    【解决方案3】:
    energy_2018.groupby(energy_2018["Date_Time"].astype('int64') / 1e9 % 86400 / 3600).mean()
    

    【讨论】:

      【解决方案4】:

      要在“分组聚合时间”内为所有行生成相同的聚合值,请结合使用 pd.groupby 和 pd.Grouper。将聚合值返回到每一行而不是重新整形的数据帧的技巧是之后使用转换函数(我使用了 numpy 的均值(np.mean),因此请务必在代码中将 numpy 导入为 np)。如果您需要更具体的灵活性(例如每 10 分钟一次,但第一分钟从某个偏移分钟而不是零开始(例如 00:02:00 而不是 00:00:00),则需要额外的参数。

      import numpy as np
      
      energy_2018["mean_hourly"] = energy_2018.groupby(pd.Grouper(key="Date_Time", freq="60Min")).transform(np.mean)
      
      Date_Time               Metered Electricity (MWh)  mean_hourly
      2016-03-27 00:03:00                   8.644511     7.726456
      2016-03-27 00:31:00                   6.808402     7.726456
      2016-03-27 01:00:00                   6.507068     5.889349
      2016-03-27 01:30:00                   5.271631     5.889349
      2016-03-27 02:00:00                   2.313497     2.313497
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2019-07-05
        • 2019-08-02
        • 2019-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多