【问题标题】:Pandas: Timestamp index rounding to the nearest 5th minutePandas:时间戳索引四舍五入到最接近的第 5 分钟
【发布时间】:2014-08-20 04:50:51
【问题描述】:

我有一个df,并以通常的时间戳作为索引:

    2011-04-01 09:30:00
    2011-04-01 09:30:10
    ...
    2011-04-01 09:36:20
    ...
    2011-04-01 09:37:30

如何为这个数据框创建一个具有相同时间戳但四舍五入到最接近的 5 分钟间隔的列?像这样:

    index                 new_col
    2011-04-01 09:30:00   2011-04-01 09:35:00        
    2011-04-01 09:30:10   2011-04-01 09:35:00
    2011-04-01 09:36:20   2011-04-01 09:40:00
    2011-04-01 09:37:30   2011-04-01 09:40:00

【问题讨论】:

标签: python pandas


【解决方案1】:

The round_to_5min(t) solution using timedelta arithmetic 是正确的,但是很复杂而且很慢。而是在 pandas 中使用漂亮的Timstamp

import numpy as np
import pandas as pd

ns5min=5*60*1000000000   # 5 minutes in nanoseconds 
pd.to_datetime(((df.index.astype(np.int64) // ns5min + 1 ) * ns5min))

让我们比较一下速度:

rng = pd.date_range('1/1/2014', '1/2/2014', freq='S')

print len(rng)
# 86401

# ipython %timeit 
%timeit pd.to_datetime(((rng.astype(np.int64) // ns5min + 1 ) * ns5min))
# 1000 loops, best of 3: 1.01 ms per loop

%timeit rng.map(round_to_5min)
# 1 loops, best of 3: 1.03 s per loop

大约快 1000 倍!

【讨论】:

  • 在处理夏令时时要小心:并非所有日子的长度都相同,您的方法可能会失败。我建议使用偏移量:pandas.pydata.org/pandas-docs/stable/…
  • @Marius Ion:这里不需要小心。一天的长度无关紧要。如果 DatetimeIndex 具有时区,则 astype 操作将转换为 UTC。只需将结果转换回您的时区即可(例如使用tz_localize("UTC").tz_convert("US/Eastern")
  • 请注意,要四舍五入到最接近的 5 分钟而不是四舍五入,它稍微复杂一些 - 也许值得将它添加到您的答案中?我在这里粘贴我的代码,但显然它在答案中看起来会更好,因为 cmets 没有格式:( ****** pd.to_datetime( ((rng.astype(np.int64) // ns5min) * ns5min) # round down + (((rng.astype(np.int64) % ns5min) > (ns5min / 2)) * ns5min) # 如果需要,添加 5min )
【解决方案2】:

可以轻松使用 pandas 的圆形功能

df["timestamp_column"].dt.round("5min")

查看here了解更多详情

【讨论】:

  • 这是最好的解决方案!
【解决方案3】:

你可以试试这样的:

def round_to_5min(t):
    delta = datetime.timedelta(minutes=t.minute%5, 
                               seconds=t.second, 
                               microseconds=t.microsecond)
    t -= delta
    if delta > datetime.timedelta(0):
        t += datetime.timedelta(minutes=5)
    return t

df['new_col'] = df.index.map(round_to_5min)

【讨论】:

  • 看起来不错,但是当我在我的数据上测试它时,我看到:2011-04-01 09:32:10 -> 2011-04-01 09:30:002011-04-01 09:32:20 -> 2011-04-01 09:30:002011-04-01 09:32:30 -> 2011-04-01 09:35:002011-04-01 09:32:40 -> 2011-04-01 09:35:00 它们都应该是 2011-04-01 09:35:00跨度>
  • 啊,在您提到的问题中,您提到了“最近”的 5 分钟,但我从您的数据中看到您希望将其四舍五入到接下来的 5 分钟。我已经确定了答案,谢谢。我假设您希望 9:30:00:00 舍入为 9:30:00:00 而不是 9:35:00:00,否则您总是可以添加 5 分钟。
  • 请问我如何从我的 new_col 中选择小时和分钟?例如,我正在尝试这样做:datetime.datetime.hour(df.new_col) 这样我就可以在小时内拥有一个新的列,但这是行不通的
  • 同种操作:df['hour'] = df.new_col.map(lambda t: t.hour)
  • 非常感谢!我真的需要学习地图的所有可能性
【解决方案4】:

我遇到了同样的问题,但使用了 datetime64p[ns] 时间戳。

我用过:

def round_to_5min(t):
    """ This function rounds a timedelta timestamp to the nearest 5-min mark"""
    t = datetime.datetime(t.year, t.month, t.day, t.hour, t.minute - t.minute%5, 0)  
    return t

接着是'map'函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 2015-01-17
    • 2018-06-03
    • 2022-01-02
    • 1970-01-01
    • 2017-12-02
    • 1970-01-01
    相关资源
    最近更新 更多