Pandas:用 groupby 中的日期重新索引,根据需要填充/维护值

gbe*_*ger 3 python pandas pandas-groupby

我有以下数据帧。

>>> df = pd.DataFrame(data={'date': ['2010-05-01', '2010-07-01', '2010-06-01', '2010-10-01'], 'id': [1,1,2,2], 'val': [50,60,70,80], 'other': ['uno', 'uno', 'dos', 'dos']})
>>> df['date'] = df['date'].apply(lambda d: pd.to_datetime(d))
>>> df
        date  id other  val
0 2010-05-01   1   uno   50
1 2010-07-01   1   uno   60
2 2010-06-01   2   dos   70
3 2010-10-01   2   dos   80
Run Code Online (Sandbox Code Playgroud)

我想扩展这个 DataFrame 以便它包含 2010 年所有月份的行。

  • DataFrame 按以下方式分组 id,因此每个 id 将有 12 行。在本例中,共有 24 行。
  • val在每月,如果从最初的数据帧不存在,应为0。
  • Theother与 有一对一的关系id,所以我想保持这种方式。

我想要的结果如下:

         date  id other  val
0  2010-01-01   1   uno    0
1  2010-02-01   1   uno    0
2  2010-03-01   1   uno    0
3  2010-04-01   1   uno    0
4  2010-05-01   1   uno    50
5  2010-06-01   1   uno    0
6  2010-07-01   1   uno    60
7  2010-08-01   1   uno    0
8  2010-09-01   1   uno    0
9  2010-10-01   1   uno    0
10 2010-11-01   1   uno    0
11 2010-12-01   1   uno    0
12 2010-01-01   2   dos    0
13 2010-02-01   2   dos    0
14 2010-03-01   2   dos    0
15 2010-04-01   2   dos    0
16 2010-05-01   2   dos    0
17 2010-06-01   2   dos    70
18 2010-07-01   2   dos    0
19 2010-08-01   2   dos    0
20 2010-09-01   2   dos    0
21 2010-10-01   2   dos    80
22 2010-11-01   2   dos    0
23 2010-12-01   2   dos    0
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

我试过 groupby('id'),然后申请。应用的函数重新索引组。但我还没有设法val用零填充,并保持other.

jez*_*ael 5

您可以使用groupby通过自定义功能reindex和灌装NaN在- Sotherffillbfill(向前和向后填充),并在val通过fillna:由恒

def f(x):
    x = x.reindex(pd.date_range('2010-01-01', '2010-12-01', freq='MS'))
    x['other'] = x['other'].ffill().bfill()
    x['val'] = x['val'].fillna(0)
    return (x)


df = df.set_index('date')
       .groupby('id')
       .apply(f).rename_axis(('id','date'))
       .drop('id', 1).reset_index()
Run Code Online (Sandbox Code Playgroud)
print (df)
    id       date other   val
0    1 2010-01-01   uno   0.0
1    1 2010-02-01   uno   0.0
2    1 2010-03-01   uno   0.0
3    1 2010-04-01   uno   0.0
4    1 2010-05-01   uno  50.0
5    1 2010-06-01   uno   0.0
6    1 2010-07-01   uno  60.0
7    1 2010-08-01   uno   0.0
8    1 2010-09-01   uno   0.0
9    1 2010-10-01   uno   0.0
10   1 2010-11-01   uno   0.0
11   1 2010-12-01   uno   0.0
12   2 2010-01-01   dos   0.0
13   2 2010-02-01   dos   0.0
14   2 2010-03-01   dos   0.0
15   2 2010-04-01   dos   0.0
16   2 2010-05-01   dos   0.0
17   2 2010-06-01   dos  70.0
18   2 2010-07-01   dos   0.0
19   2 2010-08-01   dos   0.0
20   2 2010-09-01   dos   0.0
21   2 2010-10-01   dos  80.0
22   2 2010-11-01   dos   0.0
23   2 2010-12-01   dos   0.0
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是MultiIndex.from_product通过它创建和重新索引:

mux = pd.MultiIndex.from_product([df['id'].unique(),
                                  pd.date_range('2010-01-01', '2010-12-01', freq='MS')], 
                                  names=('id','date'))

df = df.set_index(['id','date']).reindex(mux).reset_index()
df['val'] = df['val'].fillna(0)
df['other'] = df.groupby('id')['other'].apply(lambda x: x.ffill().bfill())
Run Code Online (Sandbox Code Playgroud)
print (df)
    id       date other   val
0    1 2010-01-01   uno   0.0
1    1 2010-02-01   uno   0.0
2    1 2010-03-01   uno   0.0
3    1 2010-04-01   uno   0.0
4    1 2010-05-01   uno  50.0
5    1 2010-06-01   uno   0.0
6    1 2010-07-01   uno  60.0
7    1 2010-08-01   uno   0.0
8    1 2010-09-01   uno   0.0
9    1 2010-10-01   uno   0.0
10   1 2010-11-01   uno   0.0
11   1 2010-12-01   uno   0.0
12   2 2010-01-01   dos   0.0
13   2 2010-02-01   dos   0.0
14   2 2010-03-01   dos   0.0
15   2 2010-04-01   dos   0.0
16   2 2010-05-01   dos   0.0
17   2 2010-06-01   dos  70.0
18   2 2010-07-01   dos   0.0
19   2 2010-08-01   dos   0.0
20   2 2010-09-01   dos   0.0
21   2 2010-10-01   dos  80.0
22   2 2010-11-01   dos   0.0
23   2 2010-12-01   dos   0.0
Run Code Online (Sandbox Code Playgroud)