python - 从 numpy.datetime64 转换为 pandas.tslib.Timestamp 错误?

标签 python numpy python-2.7 timestamp pandas

我有一个 python 模块,可以将数据直接加载到 numpy.ndarray 的字典中,以便在 pandas.Dataframe 中使用。但是,我注意到“NA”值存在问题。我的文件格式表示 NA 值 s -9223372036854775808 (boost::integer_traits::const_min)。我的非 NA 值按预期(使用正确的值)加载到 pandas.Dataframe 中。我相信正在发生的事情是我的模块加载到 numpy.datetime64 ndarray 中,然后将其转换为 pandas.tslib.Timestamp 列表。此转换似乎不保留 'const_min' 整数。尝试以下操作:

>>> pandas.tslib.Timestamp(-9223372036854775808)
NaT
>>> pandas.tslib.Timestamp(numpy.datetime64(-9223372036854775808))
<Timestamp: 1969-12-31 15:58:10.448384>

这是 Pandas 的错误吗?我想我可以让我的模块避免在这种情况下使用 numpy.ndarray,并使用 Pandas 不会绊倒的东西(也许预先分配 tslib.Timestamp 本身的列表。)

这是另一个意外事件发生的例子:

>>> npa = numpy.ndarray(1, dtype=numpy.datetime64)
>>> npa[0] = -9223372036854775808
>>> pandas.Series(npa)
0   NaT
>>> pandas.Series(npa)[0]
<Timestamp: 1969-12-31 15:58:10.448384>

在下面 Jeff 的评论之后,我获得了有关问题所在的更多信息。

>>> npa = numpy.ndarray(2, dtype=numpy.int64)
>>> npa[0] = -9223372036854775808
>>> npa[1] = 1326834000090451
>>> npa
array([-9223372036854775808,     1326834000090451])
>>> s_npa = pandas.Series(npa, dtype='M8[us]')
>>> s_npa
0                          NaT
1   2012-01-17 21:00:00.090451

耶!该系列保留了 NA 和我的时间戳。但是,如果我尝试从该系列创建 DataFrame,NaT 就会消失。

>>> pandas.DataFrame({'ts':s_npa})
                      ts
0 1969-12-31 15:58:10.448384
1 2012-01-17 21:00:00.090451

哼哼。一时兴起,我尝试将我的整数解释为过去纪元的纳秒。令我惊讶的是,DataFrame 工作正常:

s2_npa = pandas.Series(npa, dtype='M8[ns]')
>>> s2_npa
0                             NaT
1   1970-01-16 08:33:54.000090451
>>> pandas.DataFrame({"ts":s2_npa})
                             ts
0                           NaT
1 1970-01-16 08:33:54.000090451

当然,我的时间戳不对。我的观点是 pandas.DataFrame 在这里表现不一致。为什么在使用 dtype='M8[ns]' 时保留 NaT,而在使用 'M8[us]' 时不保留?

我目前正在使用此解决方法来转换 ,这会减慢速度,但有效:

>>> s = pandas.Series([1000*ts if ts != -9223372036854775808 else ts for ts in npa], dtype='M8[ns]')
>>> pandas.DataFrame({'ts':s})
                          ts
0                        NaT
1 2012-01-17 21:00:00.090451

(几个小时后...)

好的,我有进步了。我深入研究了代码,发现 Series 上的 repr 函数最终会调用“_format_datetime64”,它会检查“isnull”并打印出“NaT”,这解释了这两者之间的区别。

>>> pandas.Series(npa)
0   NaT
>>> pandas.Series(npa)[0]
<Timestamp: 1969-12-31 15:58:10.448384>

前者似乎尊重 NA,但它只在打印时这样做。我想可能还有其他 pandas 函数调用“isnull”并根据答案采取行动,在这种情况下,这似乎部分适用于 NA 时间戳。但是,我知道由于元素零的类型,系列是不正确的。它是一个时间戳,但应该是一个NaTType。我的下一步是深入研究 Series 的构造函数,以确定 pandas 在构造过程中何时/如何使用 NaT 值。据推测,当我指定 dtype='M8[us]' 时,它缺少一个案例...(更多内容)。

按照 Andy 在评论中的建议,我尝试使用 pandas Timestamp 来解决这个问题。它没有用。以下是这些结果的示例:

>>> npa = numpy.ndarray(1, dtype='i8')
>>> npa[0] = -9223372036854775808
>>> npa
array([-9223372036854775808])
>>> pandas.tslib.Timestamp(npa.view('M8[ns]')[0]).value
-9223372036854775808
>>> pandas.tslib.Timestamp(npa.view('M8[us]')[0]).value
-28909551616000

最佳答案

回答:没有

从技术上讲,就是这样。我在 github 上发布了这个错误并在这里得到了回应: https://github.com/pydata/pandas/issues/2800#issuecomment-13161074

“目前在索引等方面不支持纳秒以外的单位。这应该严格执行”

我用“ns”而不是“us”运行的所有测试都运行良好。我期待着 future 的发布。

对于任何感兴趣的人,我修改了我的 C++ python 模块以迭代我从磁盘加载的 int64_t 数组,并将所有内容乘以 1000,NA 值除外 (boost::integer_traits::const_min)。我担心性能,但加载时间的差异对我来说很小。 (在 Python 中做同样的事情非常非常慢。)

关于python - 从 numpy.datetime64 转换为 pandas.tslib.Timestamp 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14695309/

相关文章:

python - many2many 字段上的 Odoo 特定表单 View

bash - 启动 Python .py 脚本的别名

python - 自定义QQuickItem未绘制

python - ManagedIdentityCredential 身份验证不可用,未找到托管身份端点

Python SSL 和 Unicode 域

python - 在列中的不同位置打印 numpy

python - eclipse:运行/调试当前文件

python - SciPy.sparse 迭代求解器 : No sparse right hand side support?

python - Python 中的图像配准和仿射变换

python-2.7 - functools.wrapper - AttributeError : attribute '__doc__' of 'type' objects is not writable