将缺失的date添加到pandas数据框中

我的数据可能在给定的date有多个事件,或者在某个date没有事件。 我采取这些事件,按date计算并绘制它们。 然而,当我绘制他们时,我的两个系列并不总是匹配。

idx = pd.date_range(df['simpleDate'].min(), df['simpleDate'].max()) s = df.groupby(['simpleDate']).size() 

在上面的代码中, idx变成了30个date的范围。 2013年9月1日至2013年9月30日但是S可能只有25或26天,因为在给定date没有事件发生。 然后我得到一个AssertionError作为大小不匹配时,我尝试绘制:

 fig, ax = plt.subplots() ax.bar(idx.to_pydatetime(), s, color='green') 

有什么正确的方法来解决这个问题? 我想删除IDX中没有值的date吗?或者(我宁愿这样做)是将0的缺失date添加到系列中。我宁愿有一个30天的完整图表,0值。 如果这种方法是正确的,有关如何开始的任何build议? 我需要某种dynamicreindexfunction吗?

这是Sdf.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 ... 

一个问题是,如果有重复的值, reindex将会失败。 假设我们正在处理时间戳数据,我们希望按date进行索引:

 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-16date的重复,试图重新索引:

 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查找范围内所有date的条目:

 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可以用在填充柱上。

这里有一个很好的方法来填充丢失的date到一个数据fill_value ,用你select的fill_valuedays_back来填充数据,然后对数据days_backsorting顺序( 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 

更快的解决方法是使用.asfreq 。 这不需要创build一个新的索引在reindex调用。

 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 

在许多情况下, resample (请参阅文档)提供了一个通用的解决scheme,可以处理丢失和重复的date。 例如:

 df.resample('D').mean() 

sample是一个像groupby这样的延迟操作,所以你需要跟其他一些操作。 在这种情况下, mean很好,但你可以把任何标准的pandas方法( maxsum等)

这里是原始数据,但有一个“2013-09-03”的额外条目:

  val date 2013-09-02 2 2013-09-03 10 2013-09-03 20 2013-09-06 5 2013-09-07 1 

结果如下:

  val date 2013-09-02 2.0 2013-09-03 15.0 2013-09-04 NaN 2013-09-05 NaN 2013-09-06 5.0 2013-09-07 1.0 

如您所见,“2013-09-03”的值是该date的原始值的平均值,缺失date的值为NaN。 从这里你可以使用像fillna这样的方法或interpolate来根据需要填充fillna值。