安全地将 Pandas 日期时间系列转换为 Int64 纪元时间戳,保留空值

问题描述 投票:0回答:1

考虑一个包含一些空值的 datetime-dtype 系列:

import pandas as pd

t = pd.date_range('2022-01-01', '2022-01-02', freq='4H').to_series('t')
t.iat[2] = None
2022-01-01 00:00:00   2022-01-01 00:00:00
2022-01-01 04:00:00   2022-01-01 04:00:00
2022-01-01 08:00:00                   NaT
2022-01-01 12:00:00   2022-01-01 12:00:00
2022-01-01 16:00:00   2022-01-01 16:00:00
2022-01-01 20:00:00   2022-01-01 20:00:00
2022-01-02 00:00:00   2022-01-02 00:00:00
Freq: 4H, dtype: datetime64[ns]

这个系列的

dtype
<M8[ns]
。据我了解,这意味着底层数据在物理上存储为 64 位整数,表示自 Unix 时代开始以来的纳秒数 (
numpy.datetime64
)。但是我不知道
NaT
是如何表示的。

我想获得一个整数时间戳,表示自 Unix 纪元开始以来的纳秒数,在数据中有

NaT
的地方使用空值。因此,我似乎应该能够以某种方式检查时间戳数据类型的精度,提取原始秒数,然后根据需要放大或缩小以获得纳秒。

预期产出:

2022-01-01 00:00:00    1640995200000000000
2022-01-01 04:00:00    1641009600000000000
2022-01-01 08:00:00                   <NA>
2022-01-01 12:00:00    1641038400000000000
2022-01-01 16:00:00    1641052800000000000
2022-01-01 20:00:00    1641067200000000000
2022-01-02 00:00:00    1641081600000000000
Freq: 4H, dtype: Int64

没用的东西:

t.astype(pd.Int64Dtype())  # datetime64[ns] cannot be converted to IntegerDtype`
t.astype(float).astype(pd.Int64Dtype())  # Cannot cast DatetimeArray to dtype float64
t.map(lambda t: t.timestamp()).astype(pd.Int64Dtype())  # NaTType does not support timestamp
t.map(lambda t: t.timestamp(), na_action='ignore').astype(pd.Int64Dtype())  # 'values' contains non-numeric NA NaT

值得注意的是

.timestamp
逻辑挂在
NaT
上,我不知道如何干净地转换为“null-aware”
Int64Dtype
.

确实有效但非常丑陋的东西:

((t - pd.Timestamp(1970, 1, 1)).dt.total_seconds() * 1e09).astype(pd.Int64Dtype())

有惯用的方法吗?

python pandas numpy datetime unix-timestamp
1个回答
0
投票

编辑

我不认为有一个好的方法可以做到这一点。另一种方法:

>>> t.view(int).astype(pd.Int64Dtype()).replace(np.iinfo(np.int64).min, pd.NA)

0    1640995200000000000
1    1641009600000000000
2                   <NA>
3    1641038400000000000
4    1641052800000000000
5    1641067200000000000
6    1641081600000000000
Name: t, dtype: Int64

我不清楚你的期望。也许你可以使用

numpy

ts = t.values.astype(float)
dti = pd.to_datetime(ts)
>>> ts
array([ 1.64099520e+18,  1.64100960e+18, -9.22337204e+18,  1.64103840e+18,
        1.64105280e+18,  1.64106720e+18,  1.64108160e+18])

>>> dti
DatetimeIndex(['2022-01-01 00:00:00', '2022-01-01 04:00:00',
                               'NaT', '2022-01-01 12:00:00',
               '2022-01-01 16:00:00', '2022-01-01 20:00:00',
               '2022-01-02 00:00:00'],
              dtype='datetime64[ns]', freq=None)

>>> t
0   2022-01-01 00:00:00
1   2022-01-01 04:00:00
2                   NaT
3   2022-01-01 12:00:00
4   2022-01-01 16:00:00
5   2022-01-01 20:00:00
6   2022-01-02 00:00:00
Name: t, dtype: datetime64[ns]
© www.soinside.com 2019 - 2024. All rights reserved.