在 Python2.7 中比较 Timestamp 和 datetime64 时的奇怪行为
Posted
技术标签:
【中文标题】在 Python2.7 中比较 Timestamp 和 datetime64 时的奇怪行为【英文标题】:Strange behaviour when comparing Timestamp and datetime64 in Python2.7 【发布时间】:2019-01-21 16:18:50 【问题描述】:有没有人遇到过类似的情况,如果我们让a
是Timestamp
,b
是datetime64
,那么比较a < b
就可以了,但是b < a
返回错误。
如果a
可以与b
进行比较,我认为我们应该可以反过来比较?
例如(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】:这是一个有趣的问题。我已经进行了一些挖掘并尽力解释了其中的一些内容,尽管我仍然不明白的一件事是为什么我们得到pandas
抛出错误而不是numpy
当我们这样做时@ 987654329@。
关于您的问题:
如果a可以和b比较,我认为我们应该可以反过来比较?
这不一定是真的。这仅取决于比较运算符的实现。
以这个测试类为例:
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__
(==
) 则保持不变。
现在检查以下比较:
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'
所以回到你的情况。看着timestamps_sourceCode,我唯一能想到的是pandas.Timestamp
如果可能的话会做一些类型检查和转换。
当我们比较 a 和 b(pd.Timestamp
和 np.datetime64
)时,Timestamp.__richcmp__
函数会进行比较,如果它是 np.datetime64
类型,那么它会将其转换为 pd.Timestamp
类型并进行比较.
# 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
令我惊讶的是,我认为问题在于nanoseconds
不在时间戳中,即使您执行以下操作,np.datetime64 与 pd.Timestamp 之间的比较也会失败。
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
查看源代码似乎我们可以使用==
和!=
运算符。但即使他们没有按预期工作。请看以下示例:
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
我认为这是第 149-152 或 163-166 行的结果。如果您将==
和True
用于!=
,它们将返回False
,而不实际比较这些值。
编辑:
nanosecond
功能已添加到版本 0.23.0
。所以你可以做类似pd.Timestamp('2013-03-23T05:33:00.000000022', unit='ns')
的事情。所以是的,当您比较 np.datetime64
时,它将转换为 pd.Timestamp
和 ns
精度。
请注意,pd.Timestamp
应该是 python 的日期时间的替代品:
Timestamp 是 python 的 Datetime 的 pandas 等价物 并且在大多数情况下可以与它互换。
但是 python 的日期时间不支持纳秒 - 很好的答案在这里解释了为什么 SO_Datetime.pd.Timestamp
支持两者之间的比较,即使你的 Timestamp
有纳秒。当您将datetime
对象与pd.Timestamp
对象与ns
进行比较时,它们将使用_compare_outside_nanorange 进行比较。
回到np.datetime64
,这里要注意的一件事,正如这篇文章SO 中很好解释的那样,它是int64
类型的包装器。所以如果我执行以下操作就不足为奇了:
1 > a
a > 1
两者都会出现错误Cannot compare type 'Timestamp' with type 'int'
。
因此,当您执行b > a
时,大多数情况下在int
级别上进行比较,此比较将由np.greater()
函数np.greater 完成 - 还请查看ufunc_docs。
注意:我无法确认这一点,numpy 文档太复杂,无法阅读。如果任何 numpy 专家可以对此发表评论,那将很有帮助。
如果是这种情况,如果np.datetime64
的比较是基于int
,那么上面带有a == b
和b == a
的示例是有意义的。因为当我们执行b == a
时,我们将b
的int
值与pd.Timestamp
进行比较,这对于==
将始终返回Flase
,对于!=
将始终返回True
。
和say123 == '123'
一样,这个操作不会失败,只会返回False
。
【讨论】:
非常感谢 gyx-hh!您的回答解释了我的大部分“对 ,== 运算符的误解”!回到纳秒问题,那么 np.datetime64 和 pd.Timestamp 的兼容性似乎有一个“特征”?看到你的“a== b, b == a”代码块的结果,我有点震惊…… @Min 我刚刚用一些额外的信息更新了我的答案 非常感谢!非常感谢您的回答!以上是关于在 Python2.7 中比较 Timestamp 和 datetime64 时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
在 Python2.7 中忽略没有 continue 语句的 IndexError