[英]Add missing dates to pandas dataframe
我的數據可以在給定日期有多個事件,也可以在某個日期沒有事件。 我接受這些事件,按日期計數,然后 plot 它們。 但是,當我 plot 他們時,我的兩個系列並不總是匹配。
idx = pd.date_range(df['simpleDate'].min(), df['simpleDate'].max())
s = df.groupby(['simpleDate']).size()
在上面的代碼中, idx變成了 30 個日期的范圍。 09-01-2013 到 09-30-2013 但是S可能只有 25 或 26 天,因為在給定日期沒有發生任何事件。 然后我得到一個 AssertionError,因為當我嘗試 plot 時大小不匹配:
fig, ax = plt.subplots()
ax.bar(idx.to_pydatetime(), s, color='green')
解決這個問題的正確方法是什么? 我是否想從IDX中刪除沒有值的日期,或者(我寧願這樣做)將缺失日期添加到系列中,計數為 0。我寧願有一個 30 天的完整圖表,其中包含 0 個值。 如果這種方法是正確的,關於如何開始的任何建議? 我是否需要某種動態reindex
?
這是S的片段( df.groupby(['simpleDate']).size()
),請注意沒有 04 和 05 的條目。
09-02-2013 2
09-03-2013 10
09-06-2013 5
09-07-2013 1
您可以使用Series.reindex
:
import pandas as pd
idx = pd.date_range('09-01-2013', '09-30-2013')
s = pd.Series({'09-02-2013': 2,
'09-03-2013': 10,
'09-06-2013': 5,
'09-07-2013': 1})
s.index = pd.DatetimeIndex(s.index)
s = s.reindex(idx, fill_value=0)
print(s)
產量
2013-09-01 0
2013-09-02 2
2013-09-03 10
2013-09-04 0
2013-09-05 0
2013-09-06 5
2013-09-07 1
2013-09-08 0
...
更快的解決方法是使用.asfreq()
。 這不需要在.reindex()
中創建新索引來調用。
# "broken" (staggered) dates
dates = pd.Index([pd.Timestamp('2012-05-01'),
pd.Timestamp('2012-05-04'),
pd.Timestamp('2012-05-06')])
s = pd.Series([1, 2, 3], dates)
print(s.asfreq('D'))
2012-05-01 1.0
2012-05-02 NaN
2012-05-03 NaN
2012-05-04 2.0
2012-05-05 NaN
2012-05-06 3.0
Freq: D, dtype: float64
一個問題是,如果存在重復值, reindex
將失敗。 假設我們正在處理帶時間戳的數據,我們希望按日期對其進行索引:
df = pd.DataFrame({
'timestamps': pd.to_datetime(
['2016-11-15 1:00','2016-11-16 2:00','2016-11-16 3:00','2016-11-18 4:00']),
'values':['a','b','c','d']})
df.index = pd.DatetimeIndex(df['timestamps']).floor('D')
df
產量
timestamps values
2016-11-15 "2016-11-15 01:00:00" a
2016-11-16 "2016-11-16 02:00:00" b
2016-11-16 "2016-11-16 03:00:00" c
2016-11-18 "2016-11-18 04:00:00" d
由於重復的2016-11-16
日期,嘗試重新索引:
all_days = pd.date_range(df.index.min(), df.index.max(), freq='D')
df.reindex(all_days)
失敗:
...
ValueError: cannot reindex from a duplicate axis
(這意味着索引有重復,而不是它本身就是一個重復)
相反,我們可以使用.loc
來查找范圍內所有日期的條目:
df.loc[all_days]
產量
timestamps values
2016-11-15 "2016-11-15 01:00:00" a
2016-11-16 "2016-11-16 02:00:00" b
2016-11-16 "2016-11-16 03:00:00" c
2016-11-17 NaN NaN
2016-11-18 "2016-11-18 04:00:00" d
如果需要,可以在列系列上使用fillna
來填充空白。
另一種方法是resample
,除了缺少日期外,它還可以處理重復日期。 例如:
df.resample('D').mean()
resample
是一個類似於groupby
的延遲操作,因此您需要在它之后進行另一個操作。 在這種情況下mean
效果很好,但您也可以使用許多其他 pandas 方法,如max
、 sum
等。
這是原始數據,但有一個額外的“2013-09-03”條目:
val
date
2013-09-02 2
2013-09-03 10
2013-09-03 20 <- duplicate date added to OP's data
2013-09-06 5
2013-09-07 1
結果如下:
val
date
2013-09-02 2.0
2013-09-03 15.0 <- mean of original values for 2013-09-03
2013-09-04 NaN <- NaN b/c date not present in orig
2013-09-05 NaN <- NaN b/c date not present in orig
2013-09-06 5.0
2013-09-07 1.0
我將丟失的日期保留為 NaN 以明確其工作原理,但您可以添加fillna(0)
以按照 OP 的要求用零替換 NaN,或者使用interpolate()
之類的東西來填充基於非零值相鄰的行。
這是一種將缺失日期填充到數據框中的好方法,您可以選擇fill_value
、要填寫的 days_back 以及對數據days_back
進行排序的排序順序 ( date_order
):
def fill_in_missing_dates(df, date_col_name = 'date',date_order = 'asc', fill_value = 0, days_back = 30):
df.set_index(date_col_name,drop=True,inplace=True)
df.index = pd.DatetimeIndex(df.index)
d = datetime.now().date()
d2 = d - timedelta(days = days_back)
idx = pd.date_range(d2, d, freq = "D")
df = df.reindex(idx,fill_value=fill_value)
df[date_col_name] = pd.DatetimeIndex(df.index)
return df
您始終可以使用 DataFrame.merge(),利用從“所有日期”數據幀到“缺失日期”數據幀的左連接。 下面的例子。
## example DataFrame with missing dates between min(date) and max(date)
missing_df = pd.DataFrame({
'date':pd.to_datetime([
'2022-02-10'
,'2022-02-11'
,'2022-02-14'
,'2022-02-14'
,'2022-02-24'
,'2022-02-16'
])
,'value':[10,20,5,10,15,30]
})
## first create a DataFrame with all dates between specified start<-->end using pd.date_range()
all_dates = pd.DataFrame(pd.date_range(df['date'].min(), df['date'].max()), columns=['date'])
## from the all_dates DataFrame, left join onto the DataFrame with missing dates
new_df = all_dates.merge(right=missing_df, how='left', on='date')
new_df
s.asfreq('D').interpolate().asfreq('Q')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.