簡體   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