【问题标题】:Wrong result from timedelta operationtimedelta 操作的错误结果
【发布时间】:2013-07-05 14:39:58
【问题描述】:

dta_h 是一个 DataFrame,dta_h.Datetime 看起来像这样:

0    2013-03-01 00:00:00
1    2013-02-28 23:00:00
2    2013-02-28 22:00:00
3    2013-02-28 21:00:00
...
Name: Datetime, Length: 63001, dtype: datetime64[ns]

直到最近(我稍后会解释这意味着什么)我可以这样做来减去每个时间段的一小时:

dta_h.Datetime-np.timedelta(hours=1)

但是现在,如果我执行上述操作,我会得到:

0    2013-03-01 00:11:34.967296
1    2013-02-28 23:11:34.967296
2    2013-02-28 22:11:34.967296
3    2013-02-28 21:11:34.967296
...

这显然不是我想要的。但是,这个:

[i-timedelta(hours=1) for i in dta_h.Datetime ]

仍然产生预期的结果:

0    2013-02-28 23:00:00
1    2013-02-28 22:00:00
2    2013-02-28 21:00:00
3    2013-02-28 20:00:00
....
Length: 63001, dtype: datetime64[ns]

我 99% 确定这个问题是在我升级到 Pandas 0.11 时开始的。我一直在文档中四处寻找可能无法成功解释的版本中的任何差异。我还发现了这个帖子:

pandas handling of numpy timedelta64[ms]

指的是这个 Pandas 问题

https://github.com/pydata/pandas/issues/3009

根据我在那里读到的内容,我尝试了:

dta_h.Datetime-np.timedelta64(hours=1)

但这实际上什么也没做:

0    2013-03-01 00:00:00
1    2013-02-28 23:00:00
2    2013-02-28 22:00:00
3    2013-02-28 21:00:00
...

知道为什么 1) df-np.timedelta 停止工作,2) 为什么理解列表版本仍然有效?谢谢你的帮助。

仅供参考,我正在使用 Numpy 1.6.2,并且,我之前说过,最近从 Pandas 0.9 升级到 0.11

【问题讨论】:

    标签: python numpy pandas timedelta


    【解决方案1】:

    Numpy 在 1.6.2/1 中对于 timedeltas 有很多错误。它适用于

    In [33]: df = DataFrame(dict(date = [Timestamp('20130301'),Timestamp('20130228 23:00:00'),Timestamp('20130228 22:00:00'),Timestamp('20130228 21:00:00')]))
    
    In [34]: df
    Out[34]: 
                     date
    0 2013-03-01 00:00:00
    1 2013-02-28 23:00:00
    2 2013-02-28 22:00:00
    3 2013-02-28 21:00:00
    
    In [37]: df['date'] + timedelta(hours=1)
    Out[37]: 
    0   2013-03-01 01:00:00
    1   2013-03-01 00:00:00
    2   2013-02-28 23:00:00
    3   2013-02-28 22:00:00
    Name: date, dtype: datetime64[ns]
    
    In [38]: np.__version__
    Out[38]: '1.7.1'
    

    【讨论】:

    【解决方案2】:

    您可以以纳秒为单位使用时间:

    In [11]: df - pd.np.timedelta64(60*60*10**9)  # one hour in nanoseconds
    Out[11]:
                         date
    index
    0     2013-02-28 23:00:00
    1     2013-02-28 22:00:00
    2     2013-02-28 21:00:00
    3     2013-02-28 20:00:00
    

    timedelta64 似乎忽略了关键字参数:

    In [12]: df - pd.np.timedelta64(foo=60*60*10**9)
    Out[12]:
                         date
    index
    0     2013-03-01 00:00:00
    1     2013-02-28 23:00:00
    2     2013-02-28 22:00:00
    3     2013-02-28 21:00:00
    

    感觉应该可以使用 pandas 偏移了:

    df.date - pd.offsets.Hour(1)
    ValueError: cannot operate on a series with out a rhs of a series/ndarray of type datetime64[ns] or a timedelta
    

    目前您可以使用 apply 或 delta 属性来做到这一点:

    In [21]: df.date.apply(lambda t: t - pd.offsets.Hour(1))
    Out[21]:
    index
    0       2013-02-28 23:00:00
    1       2013-02-28 22:00:00
    2       2013-02-28 21:00:00
    3       2013-02-28 20:00:00
    Name: date, dtype: datetime64[ns]
    
    In [22]: df.date - pd.offsets.Hour(1).delta
    Out[22]:
    index
    0       2013-02-28 23:00:00
    1       2013-02-28 22:00:00
    2       2013-02-28 21:00:00
    3       2013-02-28 20:00:00
    Name: date, dtype: datetime64[ns]
    

    【讨论】:

    • 最后一个操作在 1.6.2 中仍然存在问题(不太清楚为什么,但是对于较小的值是可行的)
    • 非常感谢您的回答。此解决方案有效。但这只是一个错误的解决方法。所以我宁愿按照 Jeff 的建议升级到 1.7.0/.1。
    • NumPy 1.7.1 仍然损坏:传递给 np.timedelta64 的所有内容都被解释为纳秒,无论参数如何。
    • @dmvianna 我的理解是 timedelta64 以纳秒为单位,我不确定我理解你的意思。
    猜你喜欢
    • 2019-07-04
    • 2013-06-10
    • 1970-01-01
    • 2019-05-31
    • 2012-09-21
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多