給定一個df帶有日期索引的資料框,如下所示:
value
2017-03-31 NaN
2017-04-01 27863.7
2017-04-02 27278.5
2017-04-03 27278.5
2017-04-04 27278.5
...
2021-10-27 NaN
2021-10-28 NaN
2021-10-29 NaN
2021-10-30 NaN
2021-10-31 NaN
我可以將value列移動一年df['value'].shift(freq=pd.DateOffset(years=1)):
出去:
2018-03-31 NaN
2018-04-01 27863.7
2018-04-02 27278.5
2018-04-03 27278.5
2018-04-04 27278.5
...
2022-10-27 NaN
2022-10-28 NaN
2022-10-29 NaN
2022-10-30 NaN
2022-10-31 NaN
但是當我用它來替換原始值時df['value'] = df['value'].shift(freq=pd.DateOffset(years=1)),它會引發一個錯誤:
ValueError: cannot reindex from a duplicate axis
由于下面的代碼運行順利,所以我認為是由列中的NaNs引起的問題value:
import pandas as pd
import numpy as np
np.random.seed(2021)
dates = pd.date_range('20130101', periods=720)
df = pd.DataFrame(np.random.randint(0, 100, size=(720, 3)), index=dates, columns=list('ABC'))
df
df.B = df.B.shift(freq=pd.DateOffset(years=1))
我也嘗試使用df['value'].shift(freq=relativedelta(years= 1)),但它會生成:pandas.errors.NullFrequencyError: Cannot shift with no freq
有人可以幫助解決這個問題嗎?真誠的感謝。
uj5u.com熱心網友回復:
由于下面的代碼運行順利,所以我認為值列中的 NaN 引起的問題
不,我不這么認為。這可能是因為在您的第二個樣本中,您只有 1 個閏年。
2 個閏年的可重現誤差:
# 2018 (366 days), 2019 (365 days) and 2020 (366 days)
dates = pd.date_range('20180101', periods=365*3 1)
df = pd.DataFrame(np.random.randint(0, 100, size=(365*3 1, 3)),
index=dates, columns=list('ABC'))
df.B = df.B.shift(freq=pd.DateOffset(years=1))
...
ValueError: cannot reindex from a duplicate axis
...
下面的例子有效:
# 2017 (365 days), 2018 (366 days) and 2019 (365 days)
dates = pd.date_range('20170101', periods=365*3 1)
df = pd.DataFrame(np.random.randint(0, 100, size=(365*3 1, 3)),
index=dates, columns=list('ABC'))
df.B = df.B.shift(freq=pd.DateOffset(years=1))
只要看看value_counts:
# 2018 -> 2020
>>> df.B.shift(freq=pd.DateOffset(years=1)).index.value_counts()
2021-02-28 2 # The duplicated index
2020-12-29 1
2021-01-04 1
2021-01-03 1
2021-01-02 1
..
2020-01-07 1
2020-01-08 1
2020-01-09 1
2020-01-10 1
2021-12-31 1
Length: 1095, dtype: int64
# 2017 -> 2019
>>> df.B.shift(freq=pd.DateOffset(years=1)).index.value_counts()
2018-01-01 1
2019-12-30 1
2020-01-05 1
2020-01-04 1
2020-01-03 1
..
2019-01-07 1
2019-01-08 1
2019-01-09 1
2019-01-10 1
2021-01-01 1
Length: 1096, dtype: int64
解決方案
顯然,解決方案是洗掉重復的索引,在我們的例子中是 '2021-02-28',通過使用resample('D')聚合函式first, last, min, max, mean,sum或自定義函式:
>>> df.B.shift(freq=pd.DateOffset(years=1))['2021-02-28']
2021-02-28 41
2021-02-28 96
Name: B, dtype: int64
>>> df.B.shift(freq=pd.DateOffset(years=1))['2021-02-28'] \
.resample('D').agg(('first', 'last', 'min', 'max', 'mean', 'sum')).T
2021-02-28
first 41.0
last 96.0
min 41.0
max 96.0
mean 68.5
sum 137.0
# Choose `last` for example
df.B = df.B.shift(freq=pd.DateOffset(years=1)).resample('D').last()
請注意,您可以替換.resample(...).func為.loc[lambda x: x.index.duplicated()]
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/355125.html
下一篇:誰能解釋一下如何解決這個索引錯誤
