【问题标题】:Pandas filling missing dates and values within group with duplicate index valuesPandas 用重复的索引值填充组内缺失的日期和值
【发布时间】:2018-05-14 07:42:22
【问题描述】:

我正在尝试按用户组填充缺失的日期,但是我的索引列之一有重复的日期,所以我尝试使用唯一日期并重新索引它,然后出现长度不匹配错误。如何重新采样日频率,不会出现重复错误。

import pandas as pandas

x = pandas.DataFrame({'user': ['a','a','b','b','a'], 'dt': ['2016-01-01','2016-01-02', '2016-01-05','2016-01-06','2016-01-06'], 'val': [1,33,2,1,2]})
udates=x['dt'].unique()
x['dt'] = pandas.to_datetime(x['dt'])
dates = x.set_index(udates).resample('D').asfreq().index
users=x['user'].unique()
idx = pandas.MultiIndex.from_product((dates, users), names=['dt', 'user'])
x.set_index(['dt', 'user']).reindex(idx, fill_value=0).reset_index()
print(x)

期望的输出

          dt user  val
0  2016-01-01    a    1
2  2016-01-02    a   33
4  2016-01-03    a    0
6  2016-01-04    a    0
8  2016-01-05    a    0
10 2016-01-06    a    2
1  2016-01-01    b    0
3  2016-01-02    b    0
5  2016-01-03    b    0
7  2016-01-04    b    0
9  2016-01-05    b    2
11 2016-01-06    b    1

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    这是一种方法,重新索引每个 user 以具有从最小日期到最大日期的日期范围:

    # setup your dataframe as you had it before:
    x = pandas.DataFrame({'user': ['a','a','b','b','a'], 'dt': ['2016-01-01','2016-01-02', '2016-01-05','2016-01-06','2016-01-06'], 'val': [1,33,2,1,2]})
    udates=x['dt'].unique()
    x['dt'] = pandas.to_datetime(x['dt'])
    
    # fill with new dates:
    filled_df = (x.set_index('dt')
                 .groupby('user')
                 .apply(lambda d: d.reindex(pd.date_range(min(x.dt),
                                                          max(x.dt),
                                                          freq='D')))
                 .drop('user', axis=1)
                 .reset_index('user')
                 .fillna(0))
    
    
    >>> filled_df
               user   val
    2016-01-01    a   1.0
    2016-01-02    a  33.0
    2016-01-03    a   0.0
    2016-01-04    a   0.0
    2016-01-05    a   0.0
    2016-01-06    a   2.0
    2016-01-01    b   0.0
    2016-01-02    b   0.0
    2016-01-03    b   0.0
    2016-01-04    b   0.0
    2016-01-05    b   2.0
    2016-01-06    b   1.0
    

    【讨论】:

    • 谢谢,它有效,reset_index 对单独用户有什么意义?
    • 不客气!您实际上可以为索引的两个级别重置索引,我只是出于某种原因将您的 dt 列保留为最终数据框中的索引,但这实际上是不必要的。唯一的问题是,您需要重命名生成的列(但这不是一个很大的问题)
    【解决方案2】:

    另一种方式不如@sacul 优雅...但速度几乎相同。

    import pandas as pd
    x = pd.DataFrame({'user': ['a','a','b','b','a'],
                      'dt': ['2016-01-01','2016-01-02',
                             '2016-01-05','2016-01-06','2016-01-06'],
                      'val': [1,33,2,1,2]})
    
    users = pd.unique(x.user)
    x.dt = pd.to_datetime(x.dt)
    dates = pd.date_range(min(x.dt), max(x.dt))
    x.set_index('dt', inplace=True)
    
    df = pd.DataFrame(index=dates)
    for u in users:
        df[u] = x[x.user==u].val
    
    df = df.unstack().reset_index()
    df.rename(columns={'level_0': 'user',
                        'level_1': 'dt',
                        0: 'val'}, inplace=True)
    df.val.fillna(0, inplace=True)
    df.val = df.val.astype(int)
    df = df[['dt', 'user', 'val']]
    

    df:

                dt user  val
    0   2016-01-01    a    1
    1   2016-01-02    a   33
    2   2016-01-03    a    0
    3   2016-01-04    a    0
    4   2016-01-05    a    0
    5   2016-01-06    a    2
    6   2016-01-01    b    0
    7   2016-01-02    b    0
    8   2016-01-03    b    0
    9   2016-01-04    b    0
    10  2016-01-05    b    2
    11  2016-01-06    b    1
    

    【讨论】:

      猜你喜欢
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 2017-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      相关资源
      最近更新 更多