如何填写Pandas数据帧中的任意缺失日期?

时间:2018-05-30 15:54:49

标签: python pandas dataframe

我目前的数据框:

   |   user  |       date        | count|
   | ------  | ------------------| -----|
   | user 1  | 2017-11-09        |   3  |
   | user 1  | 2017-11-12        |   4  |
   | user 1  | 2017-11-14        |   5  |
   | user 2  | 2017-11-11        |   2  |
   | user 2  | 2017-11-12        |   6  |
   | user 2  | 2017-11-14        |   7  |

我希望它是什么:

   |   user  |       date        | count|
   | ------  | ------------------| -----|
   | user 1  | 2017-11-09        |   3  |
   | user 1  | 2017-11-10        |   0  |
   | user 1  | 2017-11-11        |   0  |
   | user 1  | 2017-11-12        |   4  |
   | user 1  | 2017-11-13        |   0  | 
   | user 1  | 2017-11-14        |   5  |
   | user 2  | 2017-11-09        |   0  |
   | user 2  | 2017-11-10        |   0  |
   | user 2  | 2017-11-11        |   2  |
   | user 2  | 2017-11-12        |   6  |
   | user 2  | 2017-11-13        |   0  | 
   | user 2  | 2017-11-14        |   7  |

有什么建议吗?我尝试过重采样方法,但我不确定它是否有效。此外,我的日期已经转换为日期时间对象。

编辑:我很感谢答案,但我已经意识到我的日期列中有多个相同的日期,并且索引现在是一个问题,因为有重复的日期。有没有办法解决不需要索引的问题(或解决它?)

3 个答案:

答案 0 :(得分:4)

使用asfreq使用DatetimeIndex,首先set_index

#if necessary convert to datetimes
#df['date'] = pd.to_datetime(df['date'])

df = df.set_index('date').asfreq('d', fill_value=0)
print (df)
            count
date             
2017-11-09      3
2017-11-10      0
2017-11-11      0
2017-11-12      4
2017-11-13      0
2017-11-14      5

如果存在重复的DatetimeIndex,则必须resample使用某些汇总功能,例如sum

df = df.set_index('date').resample('d').sum()

编辑如果不需要所有日期组合:

df = (df.set_index('date').groupby('user')['count']
        .apply(lambda x: x.asfreq('d', fill_value=0))
        .reset_index())
print (df)
     user       date  count
0  user 1 2017-11-09      3
1  user 1 2017-11-10      0
2  user 1 2017-11-11      0
3  user 1 2017-11-12      4
4  user 1 2017-11-13      0
5  user 1 2017-11-14      5
6  user 2 2017-11-11      2
7  user 2 2017-11-12      6
8  user 2 2017-11-13      0
9  user 2 2017-11-14      7

EDIT1适用于所有日期组合:

mux = pd.MultiIndex.from_product([df['user'].unique(), pd.date_range(df['date'].min(), df['date'].max())],
                                 names=['user','date'])
df = df.set_index(['user', 'date']).reindex(mux, fill_value=0).reset_index()
print (df)
      user       date  count
0   user 1 2017-11-09      3
1   user 1 2017-11-10      0
2   user 1 2017-11-11      0
3   user 1 2017-11-12      4
4   user 1 2017-11-13      0
5   user 1 2017-11-14      5
6   user 2 2017-11-09      0
7   user 2 2017-11-10      0
8   user 2 2017-11-11      2
9   user 2 2017-11-12      6
10  user 2 2017-11-13      0
11  user 2 2017-11-14      7

答案 1 :(得分:2)

您可以创建date_range并使用merge

示例:

>>> pd.date_range(start=df.date.min(), end=df.date.max(), freq='1D')

DatetimeIndex(['2017-11-09', '2017-11-10', '2017-11-11', '2017-11-12',
               '2017-11-13', '2017-11-14'],
              dtype='datetime64[ns]', freq='D')

然后

df2 = pd.DataFrame((pd.date_range(start=df.date.min(), end=df.date.max(), freq='1D')), columns=["date"])
pd.merge(df2,df, on="date", how="left").fillna(0)

date    count
0   2017-11-09  3.0
1   2017-11-10  0.0
2   2017-11-11  0.0
3   2017-11-12  4.0
4   2017-11-13  0.0
5   2017-11-14  5.0

答案 2 :(得分:1)

@ jezrael的答案非常棒!如果你想使用任意日期范围,只需添加一点:

more_dates = pd.date_range('20171101', '20171120')
df = df.reindex(more_dates, fill_value=0)

            count
2017-11-01    0.0
2017-11-02    0.0
2017-11-03    0.0
2017-11-04    0.0
2017-11-05    0.0
2017-11-06    0.0
2017-11-07    0.0
2017-11-08    0.0
2017-11-09    3.0
2017-11-10    0.0
2017-11-11    0.0
2017-11-12    4.0
2017-11-13    0.0
2017-11-14    5.0
2017-11-15    0.0
2017-11-16    0.0
2017-11-17    0.0
2017-11-18    0.0
2017-11-19    0.0
2017-11-20    0.0

感谢@jezrael的建议,编辑。