在Python2.7中比较Timestamp和datetime64时的奇怪行为

时间:2018-08-14 18:25:56

标签: python python-2.7 pandas numpy

是否有人遇到过以下类似情况,如果我们让aTimestamp,让bdatetime64,那么比较a < b就可以了,但b < a返回错误。

如果可以将ab进行比较,我认为我们应该可以进行另一种比较?

例如(Python 2.7):

>>> a
Timestamp('2013-03-24 05:32:00')
>>> b
numpy.datetime64('2013-03-23T05:33:00.000000000')
>>> a < b
False
>>> b < a
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "pandas\_libs\tslib.pyx", line 1080, in pandas._libs.tslib._Timestamp.__richcmp__ (pandas\_libs\tslib.c:20281)
TypeError: Cannot compare type 'Timestamp' with type 'long'

非常感谢!

1 个答案:

答案 0 :(得分:1)

这是一个有趣的问题。我做了一些挖掘工作,并尽了最大的努力来解释其中的一些问题,尽管我仍然不了解的一件事是,为什么我们在pandas时抛出错误而不是numpy 1}}。

关于您的问题:

  

如果a可以与b进行比较,我认为我们应该能够进行另一种比较?

这不一定是正确的。这仅取决于比较运算符的实现。

以该测试类为例:

b<a

在这里,我定义了class TestCom(int): def __init__(self, a): self.value = a def __gt__(self, other): print('TestComp __gt__ called') return True def __eq__(self, other): return self.a == other __gt__)方法,无论其他值是什么,该方法始终返回true。 <__eq__)保持不变。

现在检查以下比较:

==

回到您的情况。看着timestamps_sourceCode,我唯一想到的就是a = TestCom(9) print(a) # Output: 9 # my def of __ge__ a > 100 # Ouput: TestComp __gt__ called # True a > '100' # Ouput: TestComp __gt__ called # True '100' < a --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-486-8aee1b1d2500> in <module>() 1 # this will not use my def of __ge__ ----> 2 '100' > a TypeError: '>' not supported between instances of 'str' and 'TestCom' 进行一些类型检查和转换。

当我们比较a与b(pandas.Timestamppd.Timestamp)时,np.datetime64函数进行比较,如果类型为Timestamp.__richcmp__,则将其转换为np.datetime64键入并进行比较。

pd.Timestamp

我感到惊讶的是,我认为问题不在{stamp}中的# we can do the following to have a comparison of say b > a # this converts a to np.datetime64 - .asm8 is equivalent to .to_datetime64() b > a.asm8 # or we can confert b to datetime64[ms] b.astype('datetime64[ms]') > a # or convert to timestamp pd.to_datetime(b) > a 中,是即使您执行以下操作,np.datetime64与pd.Timestamp之间的比较也会失败。

nanoseconds

看一下源代码,看来我们可以使用a = pd.Timestamp('2013-03-24 05:32:00.00000001') a.nanosecond # returns 10 # doing the comparison again where they're both ns still fails b < a ==运算符了。但是,即使他们没有按预期工作。请看以下示例:

!=

我认为这是第149-152行或163-166行的结果。如果您将a = pd.Timestamp('2013-03-24 05:32:00.00000000') b = np.datetime64('2013-03-24 05:32:00.00000000', 'ns') b == a # returns False a == b # returns True False用于==,则它们返回True的位置,而不实际比较值。

修改!=功能是在版本nanosecond中添加的。因此,您可以执行类似0.23.0的操作。因此,是的,当您比较pd.Timestamp('2013-03-23T05:33:00.000000022', unit='ns')时,它将以np.datetime64的精度转换为pd.Timestamp

请注意,ns应该可以代替python的日期时间:

  

Timestamp与python的Datetime等效于熊猫       并且在大多数情况下可以互换。

但是python的日期时间不支持纳秒级-在这里很好地解释了为什么SO_Datetimepd.Timestamp支持两者之间的比较,即使您的pd.Timestamp包含纳秒级也是如此。当您将Timestamp对象和datetime对象与pd.Timestamp进行比较时,它们将具有_compare_outside_nanorange来进行比较。

回到ns,这里要注意的一件事,正如这篇帖子SO很好地解释的那样,它是np.datetime64类型的包装器。因此,如果执行以下操作,请不要感到惊讶:

int64

两者都会出现错误1 > a a > 1

因此,当您进行Cannot compare type 'Timestamp' with type 'int'时,比较通常是在b > a级别上进行的,该比较将通过int函数np.greater进行-还要进行看ufunc_docs

  

注意:我无法确认这一点,numpy文档太复杂而无法阅读。如果有任何麻木的专家可以对此发表评论,那将会有所帮助。

在这种情况下,如果np.greater()的比较是基于np.datetime64的,则上面的示例中inta == b才有意义。因为当我们进行b == a时,我们会将b == a的{​​{1}}值与int进行比较,因此对于b和{{1} } pd.Timestamp

与说Flase相同,该操作不会失败,只会返回==