繁体   English   中英

偏移量前滚后加上一个月偏移量后的熊猫超出纳秒时间戳

[英]pandas out of bounds nanosecond timestamp after offset rollforward plus adding a month offset

我很困惑 pandas 是如何用这些线吹出 datetime 对象的界限的:

import pandas as pd
BOMoffset = pd.tseries.offsets.MonthBegin()
# here some code sets the all_treatments dataframe and the newrowix, micolix, mocolix counters
all_treatments.iloc[newrowix,micolix] = BOMoffset.rollforward(all_treatments.iloc[i,micolix] + pd.tseries.offsets.DateOffset(months = x))
all_treatments.iloc[newrowix,mocolix] = BOMoffset.rollforward(all_treatments.iloc[newrowix,micolix]+ pd.tseries.offsets.DateOffset(months = 1))

这里all_treatments.iloc[i,micolix]pd.to_datetime(all_treatments['INDATUMA'], errors='coerce',format='%Y%m%d')设置的日期时间, INDATUMA是日期信息格式20070125

这个逻辑似乎适用于模拟数据(没有错误,日期有意义),所以目前我无法重现,而它在我的整个数据中失败并出现以下错误:

pandas.tslib.OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 2262-05-01 00:00:00

由于 pandas 以纳秒分辨率表示时间戳,因此可以使用 64 位整数表示的时间跨度被限制为大约 584 年

pd.Timestamp.min
Out[54]: Timestamp('1677-09-22 00:12:43.145225')

In [55]: pd.Timestamp.max
Out[55]: Timestamp('2262-04-11 23:47:16.854775807')

您的值超出此范围 2262-05-01 00:00:00 ,因此出现 outofbounds 错误

直接出: https ://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timestamp-limitations

解决方法:

这将强制在NaT范围之外的日期

pd.to_datetime(date_col_to_force, errors = 'coerce')

pd.to_datetime中的errors参数设置为'coerce'会导致用NaT替换超出范围的值。 引用文档

如果 'coerce',则无效解析将被设置为 NaT

例如:

datetime_variable = pd.to_datetime(datetime_variable, errors = 'coerce')

这不会修复数据(显然),但仍允许处理非 NaT 数据点。

您看到此错误消息“OutOfBoundsDatetime:超出范围纳秒时间戳:3000-12-23 00:00:00”的原因是因为 pandas 时间戳数据类型以纳秒分辨率存储日期( 来自文档)。

这意味着日期值必须在范围内

pd.Timestamp.min(1677-09-21 00:12:43.145225) and

pd.Timestamp.max(2262-04-11 23:47:16.854775807)

即使您只想要分辨率为秒或微秒的日期,pandas 仍会在内部以纳秒为单位存储它。 pandas 中没有选项可以存储上述范围之外的时间戳。

这是令人惊讶的,因为像 sql server 这样的数据库和像 numpy 这样的库允许存储超出这个范围的日期。 在大多数情况下,最多使用 64 位来存储日期。

但这里有区别。 SQL 服务器以纳秒分辨率存储日期,但精度最高为 100 ns(与 pandas 中的 1 ns 相比)。 由于空间有限(64 位),它是范围与准确性的问题。 使用 pandas 时间戳,我们有更高的准确性,但日期范围更小。

如果是 numpy (pandas 建立在 numpy 之上)datetime64 数据类型,

  • 如果日期在上述范围内,您可以将其存储在类似于 pandas 的纳秒内。
  • 或者,您可以放弃纳秒级分辨率并使用微秒级,这将为您提供更大的范围。 这是 pandas 时间戳类型中缺少的东西。

但是,如果您选择以纳秒为单位存储并且日期超出范围,那么 numpy 将自动环绕该日期,您可能会得到意想不到的结果(在下面的第 4 个解决方案中引用)。

np.datetime64("3000-06-19T08:17:14.073456178", dtype="datetime64[ns]")
> numpy.datetime64('1831-05-11T09:08:06.654352946')

现在有了熊猫,我们有以下选择,

import pandas as pd
data = {'Name': ['John', 'Sam'], 'dob': ['3000-06-19T08:17:14', '2000-06-19T21:17:14']}
my_df = pd.DataFrame(data)

1)如果您可以丢失超出范围的数据,那么只需使用以下参数将超出范围的日期转换为 NaT(不是时间)。

my_df['dob'] = pd.to_datetime(my_df['dob'], errors = 'coerce')

在此处输入图像描述

2)如果您不想丢失数据,则可以将值转换为 python 日期时间类型。 这里的“dob”列是 pandas 对象类型,但单个值将是 python datetime 类型。 然而这样做我们将失去向量化函数的好处。

import datetime as dt
my_df['dob'] = my_df['dob'].apply(lambda x: dt.datetime.strptime(x,'%Y-%m-%dT%H:%M:%S') if type(x)==str else pd.NaT)
print(type(my_df.iloc[0][1]))
> <class 'datetime.datetime'>

在此处输入图像描述

3)如果可能,另一种选择是使用 numpy 而不是 pandas 系列。 对于 pandas 数据框,您可以将系列(或 df 中的列)转换为 numpy 数组。 分别处理数据,然后将其加入数据帧。

4)我们也可以按照文档中的建议使用 pandas 时间跨度 在使用此数据类型之前,请检查差异 b/w 时间戳和时间段。 此处的日期范围和频率与 numpy 类似(上面在 numpy 部分中提到过)。

my_df['dob'] = my_df['dob'].apply(lambda x: pd.Period(x, freq='ms'))

在此处输入图像描述

以上都不是很好,因为它会删除您的数据。 但是,您只能维护和编辑您的转换:

# convertin from epoch to datatime mantainig the nanoseconds timestamp
xbarout= pd.to_datetime(xbarout.iloc[:,0],unit='ns')

您可以尝试使用 datetime 库中的 strptime() 以及 lambda 表达式将文本转换为系列对象中的日期值:

例子:

df['F'].apply(lambda x: datetime.datetime.strptime(x, '%m/%d/%Y %I:%M:%S') if type(x)==str else np.NaN)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM