复制所有缺失日期数据帧的前一天行

The*_*lon 5 python dataframe pandas

以下是输入pandas数据帧的示例:

**LastUpdate**                         **Whatever**                 ...

2017-12-30                              xxx                          ...

2017-12-30                              yyy                          ...

2017-12-30                              zzz                          ...

2018-01-01                              yyy                          ...

2018-01-03                              zzz                          ...
Run Code Online (Sandbox Code Playgroud)

这是预期的DF(输出):

**LastUpdate**                         **Whatever**                 ...

2017-12-30                              xxx                          ...

2017-12-30                              yyy                          ...

2017-12-30                              zzz                          ...

2017-12-31                              xxx                          ...

2017-12-31                              yyy                          ...

2017-12-31                              zzz                          ...

2018-01-01                              yyy                          ...

2018-01-02                              yyy                          ...

2018-01-03                              zzz                          ...
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,数据中缺少的日期只会复制前一天的行,因此我只是用(所有)前一天的数据填充缺失的日期.问题是每天的行数可能不同,所以这并没有真正帮助.

重要提示:两天之间可能只有一天缺失(可能从2018-01-01到2018-01-05,所以我需要在这两天之间用相同的数据添加所有缺失的天数(具有与2018-01-01完全相同的行数/内容数,是可用数据的最后一天.

我已经做了一些研究并提出了resample,ffillreset_index方法,但看起来它不适合我的具体情况,因为它需要一个唯一的日期索引,这不是这里的情况,因为一天可能有几行相关.

到目前为止我尝试过的:

df['Last Update'] = pd.to_datetime(df['Last Update'])
df.set_index("Last Update", inplace=True)
dfResult = df.resample('D').ffill().reset_index()
Run Code Online (Sandbox Code Playgroud)

产量cannot reindex a non-unique index with a method or limit(这完全有道理)但我真的无法找到实现我想做的事情的方法.如果有任何不清楚或者您需要更多其他信息,请告诉我,任何帮助将不胜感激

cs9*_*s95 5

设置

# This solution should also work for multiple columns.
# Setup.
df['Whatever2'] = df['Whatever'].map({'xxx':'a', 'yyy':'b', 'zzz':'c'})
df

  LastUpdate Whatever Whatever2
0 2017-12-30      xxx         a
1 2017-12-30      yyy         b
2 2017-12-30      zzz         c
3 2018-01-01      yyy         b
4 2018-01-05      zzz         c
5 2018-01-06      xxx         a
6 2018-01-06      xxx         a
7 2018-01-09      yyy         b
Run Code Online (Sandbox Code Playgroud)

解决方案

一遍又一遍地使用set_index+ 。unstackreindexstack

# If required, convert "LastUpdate" to `datetime`.
# df['LastUpdate'] = pd.to_datetime(df['LastUpdate'], errors='coerce')

(df.set_index(['LastUpdate', df.groupby('LastUpdate').cumcount()])
   .unstack(1, fill_value='')
   .reindex(pd.date_range(df['LastUpdate'].min(), df['LastUpdate'].max()))
   .ffill()
   .replace('', np.nan)
   .stack(1)
   .reset_index(level=1, drop=True)
   .rename_axis('LastUpdate').reset_index())

   LastUpdate Whatever Whatever2
0  2017-12-30      xxx         a
1  2017-12-30      yyy         b
2  2017-12-30      zzz         c
3  2017-12-31      xxx         a
4  2017-12-31      yyy         b
5  2017-12-31      zzz         c
6  2018-01-01      yyy         b
7  2018-01-02      yyy         b
8  2018-01-03      yyy         b
9  2018-01-04      yyy         b
10 2018-01-05      zzz         c
11 2018-01-06      xxx         a
12 2018-01-06      xxx         a
13 2018-01-07      xxx         a
14 2018-01-07      xxx         a
15 2018-01-08      xxx         a
16 2018-01-08      xxx         a
17 2018-01-09      yyy         b
Run Code Online (Sandbox Code Playgroud)

细节

首先,设置索引。用于cumcount获取重复日期的计数。这是确定新日期必须重复多少次所必需的。

df.groupby('LastUpdate').cumcount().to_numpy()
# array([0, 1, 2, 0, 0, 0, 1, 0])

df.set_index(['LastUpdate', df.groupby('LastUpdate').cumcount()])

             Whatever Whatever2
LastUpdate                     
2017-12-30 0      xxx         a
           1      yyy         b
           2      zzz         c
2018-01-01 0      yyy         b
2018-01-05 0      zzz         c
2018-01-06 0      xxx         a
           1      xxx         a
2018-01-09 0      yyy         b
Run Code Online (Sandbox Code Playgroud)

接下来,使用unstack. 我使用fill_value=''来充当接下来的步骤(向前填充)的块。

_.unstack(1, fill_value='')


           Whatever           Whatever2      
                  0    1    2         0  1  2
LastUpdate                                   
2017-12-30      xxx  yyy  zzz         a  b  c
2018-01-01      yyy                   b      
2018-01-05      zzz                   c      
2018-01-06      xxx  xxx              a  a   
2018-01-09      yyy                   b      
Run Code Online (Sandbox Code Playgroud)

您现在可以使用reindex包含缺失的日期:

_.reindex(pd.date_range(df['LastUpdate'].min(), df['LastUpdate'].max()))

           Whatever           Whatever2          
                  0    1    2         0    1    2
2017-12-30      xxx  yyy  zzz         a    b    c
2017-12-31      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-01      yyy                   b          
2018-01-02      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-03      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-04      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-05      zzz                   c          
2018-01-06      xxx  xxx              a    a     
2018-01-07      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-08      NaN  NaN  NaN       NaN  NaN  NaN
2018-01-09      yyy                   b          
Run Code Online (Sandbox Code Playgroud)

现在,前向填充将昨天的第 i数据分配到缺失日期的相应位置。

_.ffill()

           Whatever           Whatever2      
                  0    1    2         0  1  2
2017-12-30      xxx  yyy  zzz         a  b  c
2017-12-31      xxx  yyy  zzz         a  b  c
2018-01-01      yyy                   b      
2018-01-02      yyy                   b      
2018-01-03      yyy                   b      
2018-01-04      yyy                   b      
2018-01-05      zzz                   c      
2018-01-06      xxx  xxx              a  a   
2018-01-07      xxx  xxx              a  a   
2018-01-08      xxx  xxx              a  a   
2018-01-09      yyy                   b      
Run Code Online (Sandbox Code Playgroud)

将填充值替换为 NaN 和stack

_.replace('', np.nan).stack(1)

             Whatever Whatever2
2017-12-30 0      xxx         a
           1      yyy         b
           2      zzz         c
2017-12-31 0      xxx         a
           1      yyy         b
           2      zzz         c
2018-01-01 0      yyy         b
2018-01-02 0      yyy         b
2018-01-03 0      yyy         b
2018-01-04 0      yyy         b
2018-01-05 0      zzz         c
2018-01-06 0      xxx         a
           1      xxx         a
2018-01-07 0      xxx         a
           1      xxx         a
2018-01-08 0      xxx         a
           1      xxx         a
2018-01-09 0      yyy         b
Run Code Online (Sandbox Code Playgroud)

之后,它正在清理索引。