【问题标题】:How to resample a dataframe with different functions applied to each column?如何重新采样具有应用于每列的不同函数的数据框?
【发布时间】:2012-04-18 17:17:02
【问题描述】:

我有一个熊猫dataframe 的温度和辐射时间序列。时间分辨率为 1 分钟,以常规步长。

import datetime
import pandas as pd
import numpy as np

date_times = pd.date_range(datetime.datetime(2012, 4, 5, 8, 0),
                           datetime.datetime(2012, 4, 5, 12, 0),
                           freq='1min')
tamb = np.random.sample(date_times.size) * 10.0
radiation = np.random.sample(date_times.size) * 10.0
frame = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation},
                     index=date_times)
frame
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 241 entries, 2012-04-05 08:00:00 to 2012-04-05 12:00:00
Freq: T
Data columns:
radiation    241  non-null values
tamb         241  non-null values
dtypes: float64(2)

如何将这个dataframe 下采样到一小时的分辨率,计算温度的每小时平均值和辐射的每小时总和?

【问题讨论】:

    标签: python numpy time-series pandas


    【解决方案1】:

    在 pandas 0.18 中,重采样 API 发生了变化(请参阅 docs)。 所以对于 pandas >= 0.18 的答案是:

    In [31]: frame.resample('1H').agg({'radiation': np.sum, 'tamb': np.mean})
    Out[31]: 
                             tamb   radiation
    2012-04-05 08:00:00  5.161235  279.507182
    2012-04-05 09:00:00  4.968145  290.941073
    2012-04-05 10:00:00  4.478531  317.678285
    2012-04-05 11:00:00  4.706206  335.258633
    2012-04-05 12:00:00  2.457873    8.655838
    

    旧答案:

    我正在回答我的问题以反映pandas &gt;= 0.8 中与时间序列相关的变化(所有其他答案都已过时)。

    使用 pandas >= 0.8 答案是:

    In [30]: frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean})
    Out[30]: 
                             tamb   radiation
    2012-04-05 08:00:00  5.161235  279.507182
    2012-04-05 09:00:00  4.968145  290.941073
    2012-04-05 10:00:00  4.478531  317.678285
    2012-04-05 11:00:00  4.706206  335.258633
    2012-04-05 12:00:00  2.457873    8.655838
    

    【讨论】:

    • 这可以扩展到每列的函数列表:frame.resample('1H', how={'radiation': [np.sum, np.min], 'tamb': np.mean})。生成的 DataFrame 在其列上有一个 MultiIndex,原始列名称为 0 级,函数名称为 1 级。
    • 补充我之前的评论:除了每列的函数列表,您还可以使用字典,其中键是新列名,值是要使用的函数:@987654326 @
    • 说是否要在结果中添加新列,例如重采样期间每一行的count()。
    • @codingknob:对不起,我不明白你的评论。
    • 在 .bfill() 的情况下你会建议什么? np.bfill() 不存在
    【解决方案2】:

    您还可以使用pandas.DateRange objects 的asof 方法进行下采样。

    In [21]: hourly = pd.DateRange(datetime.datetime(2012, 4, 5, 8, 0),
    ...                          datetime.datetime(2012, 4, 5, 12, 0),
    ...                          offset=pd.datetools.Hour())
    
    In [22]: frame.groupby(hourly.asof).size()
    Out[22]: 
    key_0
    2012-04-05 08:00:00    60
    2012-04-05 09:00:00    60
    2012-04-05 10:00:00    60
    2012-04-05 11:00:00    60
    2012-04-05 12:00:00    1
    In [23]: frame.groupby(hourly.asof).agg({'radiation': np.sum, 'tamb': np.mean})
    Out[23]: 
                         radiation  tamb 
    key_0                                
    2012-04-05 08:00:00  271.54     4.491
    2012-04-05 09:00:00  266.18     5.253
    2012-04-05 10:00:00  292.35     4.959
    2012-04-05 11:00:00  283.00     5.489
    2012-04-05 12:00:00  0.5414     9.532
    

    【讨论】:

      【解决方案3】:

      为了吸引您,在 pandas 0.8.0 中(在 GitHub 上的 timeseries 分支中进行大量开发),您将能够:

      In [5]: frame.convert('1h', how='mean')
      Out[5]: 
                           radiation      tamb
      2012-04-05 08:00:00   7.840989  8.446109
      2012-04-05 09:00:00   4.898935  5.459221
      2012-04-05 10:00:00   5.227741  4.660849
      2012-04-05 11:00:00   4.689270  5.321398
      2012-04-05 12:00:00   4.956994  5.093980
      

      上述方法是当前生产版 pandas 的正确策略。

      【讨论】:

      • 谢谢,但我想要的是frame.convert('1h', how={'radiation': 'sum, 'tamb': 'mean'})。这是 0.8 中的选项吗?
      • @Wes McKinney 这在 0.8 中应该是 resample,不是吗?
      • 如果您更新您的答案,我会接受。否则我认为你应该删除它,因为它会将用户指向错误的方向。
      【解决方案4】:

      您需要像这样使用groupby:

      grouped = frame.groupby(lambda x: x.hour)
      grouped.agg({'radiation': np.sum, 'tamb': np.mean})
      # Same as: grouped.agg({'radiation': 'sum', 'tamb': 'mean'})
      

      输出为:

              radiation      tamb
      key_0                      
      8      298.581107  4.883806
      9      311.176148  4.983705
      10     315.531527  5.343057
      11     288.013876  6.022002
      12       5.527616  8.507670
      

      所以本质上我是在小时值上进行拆分,然后计算tamb 的平均值和radiation 的总和并返回DataFrame(类似于R 的ddply 的方法)。有关更多信息,我会查看 groupby 和 this 博客文章的文档页面。

      编辑:为了使这个比例更好一点,你可以这样分组:

      grouped = frame.groupby(lambda x: (x.day, x.hour))
      grouped.agg({'radiation': 'sum', 'tamb': 'mean'})
                radiation      tamb
      key_0                        
      (5, 8)   298.581107  4.883806
      (5, 9)   311.176148  4.983705
      (5, 10)  315.531527  5.343057
      (5, 11)  288.013876  6.022002
      (5, 12)    5.527616  8.507670
      

      【讨论】:

        猜你喜欢
        • 2017-09-30
        • 1970-01-01
        • 2019-05-27
        • 2019-04-15
        • 1970-01-01
        • 2020-11-18
        • 2018-04-28
        • 2019-03-25
        • 2019-02-10
        相关资源
        最近更新 更多