【问题标题】:Resample a pandas dataframe by an arbitrary factor按任意因子重新采样 pandas 数据帧
【发布时间】:2013-11-22 15:35:33
【问题描述】:

如果您的索引使用日期时间索引,Pandas 重采样非常方便,但我还没有找到一个简单的实现来按任意因子重采样。例如,只需将每个索引视为任意索引,并对数据帧重新采样,使其结果长度缩短 4 倍(并且比仅获取每 4 个数据点更智能)。

这对于处理比日期时间短得多的数据的任何人都非常有用。例如,在我的情况下,我想将音频矢量从 44KHz 重新采样到 11KHz。现在我必须使用 scipy 的“抽取”功能,然后将其重新转换回数据帧(使用 dataframe.apply 不起作用,因为它改变了数据帧的长度)。

有人对如何做到这一点有任何建议吗?

【问题讨论】:

    标签: python pandas scipy signal-processing


    【解决方案1】:

    您可以使用DatetimeIndex 重新采样高频数据(精度高达纳秒,警告:我相信这仅在即将发布的 0.13 版本中可用)。我已经成功地使用 pandas 重新采样了 24KHz 范围内的电生理数据。这是一个例子:

    In [97]: index = date_range('1/1/2001 00:00:00', '1/1/2001 00:00:01', freq='22727N')
    
    In [98]: index
    Out[98]:
    <class 'pandas.tseries.index.DatetimeIndex'>
    [2001-01-01 00:00:00, ..., 2001-01-01 00:00:00.999988]
    Length: 44001, Freq: 22727N, Timezone: None
    
    In [99]: s = Series(randn(index.size), index=index)
    
    In [100]: s.head(10)
    Out[100]:
    2001-01-01 00:00:00          -0.820
    2001-01-01 00:00:00.000022   -1.141
    2001-01-01 00:00:00.000045    1.577
    2001-01-01 00:00:00.000068   -1.031
    2001-01-01 00:00:00.000090    0.343
    2001-01-01 00:00:00.000113   -0.424
    2001-01-01 00:00:00.000136   -0.753
    2001-01-01 00:00:00.000159    0.411
    2001-01-01 00:00:00.000181    0.238
    2001-01-01 00:00:00.000204    1.048
    Freq: 22727N, dtype: float64
    
    In [101]: s.resample(s.index.freq * 4, how='mean')
    Out[101]:
    2001-01-01 00:00:00          -0.354
    2001-01-01 00:00:00.000090   -0.106
    2001-01-01 00:00:00.000181    0.245
    2001-01-01 00:00:00.000272    0.568
    2001-01-01 00:00:00.000363    0.047
    2001-01-01 00:00:00.000454   -0.560
    2001-01-01 00:00:00.000545   -0.485
    2001-01-01 00:00:00.000636   -0.271
    2001-01-01 00:00:00.000727   -0.457
    2001-01-01 00:00:00.000818    0.078
    2001-01-01 00:00:00.000909    0.394
    2001-01-01 00:00:00.000999    0.185
    2001-01-01 00:00:00.001090   -0.441
    2001-01-01 00:00:00.001181    0.300
    2001-01-01 00:00:00.001272   -0.521
    ...
    2001-01-01 00:00:00.998715   -0.045
    2001-01-01 00:00:00.998806   -0.044
    2001-01-01 00:00:00.998897    0.090
    2001-01-01 00:00:00.998988    0.748
    2001-01-01 00:00:00.999078   -0.179
    2001-01-01 00:00:00.999169    0.451
    2001-01-01 00:00:00.999260   -1.041
    2001-01-01 00:00:00.999351   -0.476
    2001-01-01 00:00:00.999442   -0.234
    2001-01-01 00:00:00.999533   -0.719
    2001-01-01 00:00:00.999624   -0.606
    2001-01-01 00:00:00.999715   -0.032
    2001-01-01 00:00:00.999806   -0.296
    2001-01-01 00:00:00.999897   -0.044
    2001-01-01 00:00:00.999988   -0.951
    Freq: 90908N, Length: 11001
    

    您可以将一个可调用对象传递给how,这将允许您“做一些更智能的事情”。 pandas 默认取给定时间段内的平均值(在本例中,这是每块 22727 个样本的平均值)。

    【讨论】:

    • 这是一个聪明的解决方案,也是我最近一直在思考的问题。不久前我曾尝试使用日期时间索引,但我认为我可以使用的最小单位更改是微秒,当我上/下采样时,它偶尔会引入一些烦人的跳跃。您是否也对元数据进行过此操作?我自己实际上是在做电生理学神经科学研究,所以我希望在时基之上的 MultiIndex 中包含试验/试验类型信息......
    【解决方案2】:

    我有一个肮脏而有效的答案要提议:

    如果您的数据框称为数据,请首先将您的索引列复制到其他列中:

    for i in data.index:
        data.at[data.index[i],'num']=i
    

    然后使用 panda 的复杂选择能力简单地重新采样:

    data_resampled = data[data['num']%frequency==0]
    

    可以在不复制索引列的情况下执行此操作,或者很可能存在一个专用命令来使其更优雅。然而,这行得通。

    【讨论】:

      【解决方案3】:

      好的,这可能是一种更 Pythonic 的方式,在一行中用于非日期时间索引:

      data_resampled = data.reset_index()[data.reset_index()['index']%frequency==0]
      

      这样您就可以省去 for 循环,并获得一个“索引”列,如果需要,您可以在之后丢弃该列。

      【讨论】:

        猜你喜欢
        • 2017-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-01
        • 2020-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多