【问题标题】:Python: fill missing dates for each groupPython:为每个组填充缺失的日期
【发布时间】:2018-02-12 18:56:33
【问题描述】:

我有一个如下所示的 DataFrame:

x = pd.DataFrame({'user': ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b','b'], 'rd': ['2016-01-01', '2016-01-01' ,
                        '2016-02-01', '2016-02-01', '2016-02-01',  '2016-05-01', '2016-05-01', 
                            '2016-06-01','2016-06-01', '2016-06-01'],
                  'fd' : ['2016-02-01', '2016-04-01', '2016-03-01', '2016-04-01', '2016-05-01',
                         '2016-06-01', '2016-07-01', '2016-08-01', '2016-07-01', '2016-09-01'],
                  'val': [3, 4, 16, 7, 9, 2, 5, 11, 20, 1]})

x.head(6)

       fd          rd     user val
0   2016-02-01  2016-01-01  a   3
1   2016-04-01  2016-01-01  a   4
2   2016-03-01  2016-02-01  a   16
3   2016-04-01  2016-02-01  a   7
4   2016-05-01  2016-02-01  a   9
5   2016-06-01  2016-05-01  b   2

x['rd'] = pd.to_datetime(x['rd'])
x['fd'] = pd.to_datetime(x['fd'])

对于每个 rd 日期,我希望有接下来 3 个月的日期。例如:

rd = 2016-01-01 

我想要:

fd = [2016-02-01, 2016-03-01, 2016-04-01]

基本上:对于每个 rd 日期,我希望接下来的 3 个月作为 fd 日期。 在我的数据集中,我在 rd (2016-03-01, 2016-04-01) 和 fd 中都缺少日期,一旦我有了 rd 日期 (rd = 2016-01-01, fd missing = 2016-03-01)

此外,我有 2 个不同的用户 x['user'].unique() = ['a', 'b'] 。 因此,我可能在一个用户、另一个用户或两者中都缺少日期(“rd”和“fd”)。

我想要实现的是一种为所有用户获取包含所有日期的数据框的有效方法。

问题从已经回答的Question 开始,但这里的问题有点复杂,因为我无法将 Multiindex 用于手头的问题。

到目前为止,我所做的是创建 2 列日期:

index = pd.date_range(x['rd'].min(),
                          x['rd'].max(), freq='MS')

from datetime import datetime
from dateutil.relativedelta import relativedelta
def add_months(date):
   fcs_dates = [date + relativedelta(months = 1), date + relativedelta(months = 2), date + relativedelta(months = 3)]
   return fcs_dates

fcs_dates = list(map(lambda x: add_months(x), index.tolist()))
fcs_dates = [j for i in fcs_dates for j in i]
index3 = index.tolist()*3
index3.sort()

所以输出是:

list(zip(index3, fcs_dates))[:5]

[(Timestamp('2016-01-01 00:00:00', freq='MS'),
  Timestamp('2016-02-01 00:00:00', freq='MS')),
 (Timestamp('2016-01-01 00:00:00', freq='MS'),
  Timestamp('2016-03-01 00:00:00', freq='MS')),
 (Timestamp('2016-01-01 00:00:00', freq='MS'),
  Timestamp('2016-04-01 00:00:00', freq='MS')),
 (Timestamp('2016-02-01 00:00:00', freq='MS'),
  Timestamp('2016-03-01 00:00:00', freq='MS')),
 (Timestamp('2016-02-01 00:00:00', freq='MS'),
  Timestamp('2016-04-01 00:00:00', freq='MS'))]

不幸的是,我不知道如何将其插入 MultiIndex 函数。

感谢您的帮助

【问题讨论】:

    标签: python pandas datetime multi-index


    【解决方案1】:

    我在理解您的问题时遇到了很多麻烦,我无法让 index3 在 python 3 中工作。

    您是否正在寻找类似的东西?

    indx = pd.MultiIndex.from_product([['a', 'b'], [index], [pd.DatetimeIndex(fcs_dates)]])
    

    如果您能够在多索引中构建所需的级别,则 from_product 将使用其笛卡尔积来创建索引。

    【讨论】:

    • 谢谢,我用日期转换为日期时间编辑了问题。它应该可以工作。不幸的是,这不是我想要的:在 index 和 fcs_dates 之间进行乘积会给我这样的行:rd = 2017-01-01 fd = 2017-07-01 我不想...
    【解决方案2】:

    因此,我通过为每个组(用户)进行左连接解决了我自己的问题,其中左数据框是用日期构造的数据框。

    pd.DataFrame 带日期:

    left_df = pd.DataFrame({'rd' : index_3, 'fd' : fcs_dates})
    left_df['rd'] = left_df['rd'].astype(str)
    left_df['fd'] = left_df['fd'].astype(str)
    

    按用户DataFrame分组:

    df_gr = x.groupby(['user'])
    list_gr = []
    for i, gr in df_gr:
        gr_new = pd.merge(left_df, gr, left_on= ['rd', 'fd'],
                                  right_on = ['rd', 'fd'],
                                 how = 'left')
        list_gr.append(gr_new)
    
    df_final = pd.concat(list_gr)    
    

    最终数据框:

    fd  rd  user    val
    
    0   2016-02-01  2016-01-01  a   3.0
    1   2016-03-01  2016-01-01  NaN NaN
    2   2016-04-01  2016-01-01  a   4.0
    3   2016-03-01  2016-02-01  a   16.0
    4   2016-04-01  2016-02-01  a   7.0
    5   2016-05-01  2016-02-01  a   9.0
    6   2016-04-01  2016-03-01  NaN NaN
    7   2016-05-01  2016-03-01  NaN NaN
    8   2016-06-01  2016-03-01  NaN NaN
    9   2016-05-01  2016-04-01  NaN NaN
    10  2016-06-01  2016-04-01  NaN NaN
    11  2016-07-01  2016-04-01  NaN NaN
    12  2016-06-01  2016-05-01  NaN NaN
    13  2016-07-01  2016-05-01  NaN NaN
    14  2016-08-01  2016-05-01  NaN NaN
    15  2016-07-01  2016-06-01  NaN NaN
    16  2016-08-01  2016-06-01  NaN NaN
    17  2016-09-01  2016-06-01  NaN NaN
    0   2016-02-01  2016-01-01  NaN NaN
    1   2016-03-01  2016-01-01  NaN NaN
    2   2016-04-01  2016-01-01  NaN NaN
    3   2016-03-01  2016-02-01  NaN NaN
    4   2016-04-01  2016-02-01  NaN NaN
    5   2016-05-01  2016-02-01  NaN NaN
    6   2016-04-01  2016-03-01  NaN NaN
    7   2016-05-01  2016-03-01  NaN NaN
    8   2016-06-01  2016-03-01  NaN NaN
    9   2016-05-01  2016-04-01  NaN NaN
    10  2016-06-01  2016-04-01  NaN NaN
    11  2016-07-01  2016-04-01  NaN NaN
    12  2016-06-01  2016-05-01  b   2.0
    13  2016-07-01  2016-05-01  b   5.0
    14  2016-08-01  2016-05-01  NaN NaN
    15  2016-07-01  2016-06-01  b   20.0
    16  2016-08-01  2016-06-01  b   11.0
    17  2016-09-01  2016-06-01  b   1.0
    

    很遗憾,我认为这不是最快的方法,但我得到了我想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-31
      • 1970-01-01
      • 2019-07-22
      • 2021-07-22
      • 1970-01-01
      • 2020-12-07
      • 2015-10-09
      • 2020-04-08
      相关资源
      最近更新 更多