我的数据可以有多个事件在一个给定的日期或没有事件在一个日期。我把这些事件,按日期计数,然后画出来。然而,当我绘制它们时,我的两个级数并不总是匹配的。
idx = pd.date_range(df['simpleDate'].min(), df['simpleDate'].max())
s = df.groupby(['simpleDate']).size()
在上面的代码中,idx变成了一个范围,比如说30个日期。09-01-2013至09-30
但是S可能只有25或26天,因为在给定的日期内没有任何事件发生。然后我得到一个AssertionError的大小不匹配时,我试图绘制:
fig, ax = plt.subplots()
ax.bar(idx.to_pydatetime(), s, color='green')
解决这个问题的正确方法是什么?我是想从IDX中删除没有值的日期,还是(我宁愿这样做)将计数为0的缺失日期添加到系列中。我宁愿有一个完整的30天的图表,值为0。如果这种方法是正确的,有什么开始的建议吗?我是否需要某种动态重索引函数?
下面是S (df.groupby(['simpleDate']).size())的一个片段,注意04和05没有条目。
09-02-2013 2
09-03-2013 10
09-06-2013 5
09-07-2013 1
这里有一个很好的方法来填充缺失的日期到一个数据帧,你可以选择fill_value, 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
这里有一个很好的方法来填充缺失的日期到一个数据帧,你可以选择fill_value, 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
另一种方法是重新采样,除了处理丢失的日期外,还可以处理重复的日期。例如:
df.resample('D').mean()
Resample是一个像groupby一样的延迟操作,因此您需要在它之后执行另一个操作。在这种情况下,mean工作得很好,但你也可以使用许多其他的熊猫方法,如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,以便清楚地说明这是如何工作的,但是您可以根据OP的要求添加fillna(0)来将nan替换为零,或者使用interpolate()之类的东西来根据相邻行填充非零值。
你总是可以使用DataFrame.merge()利用从'All Dates' DataFrame到'Missing Dates' DataFrame的左连接。下面的例子。
# 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(missing_df['date'].min(), missing_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')