Pandas:使用 groupby 中的日期重新索引,filling/maintaining 值视情况而定
Pandas: reindex with dates in groupby, filling/maintaining values as appropriate
我有以下数据框。
>>> 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
我想扩展此 DataFrame,使其包含 2010 年所有月份的行。
- DataFrame 按
id
分组,因此每个 ID 有 12 行。在本例中,共有 24 行。
- 每个月的
val
,如果初始 DataFrame 中不存在,则应为 0。
other
与 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
我尝试过的:
我试过groupby('id'),然后申请。应用的函数重新索引该组。但是我还没有设法既用零填充 val
又保持 other
.
您可以通过自定义函数使用 groupby
和 reindex
并填充 NaN
s - 在 other
中 ffill
和 bfill
(向前和向后填充)和在 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()
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
另一个解决方案是创建 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())
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
我有以下数据框。
>>> 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
我想扩展此 DataFrame,使其包含 2010 年所有月份的行。
- DataFrame 按
id
分组,因此每个 ID 有 12 行。在本例中,共有 24 行。 - 每个月的
val
,如果初始 DataFrame 中不存在,则应为 0。 other
与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
我尝试过的:
我试过groupby('id'),然后申请。应用的函数重新索引该组。但是我还没有设法既用零填充 val
又保持 other
.
您可以通过自定义函数使用 groupby
和 reindex
并填充 NaN
s - 在 other
中 ffill
和 bfill
(向前和向后填充)和在 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()
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
另一个解决方案是创建 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())
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