Pandas 使用 Groupby 的窗口未按预期工作
Pandas Windowing with Groupby not Working as Expected
我有一个 pandas 数据框,我试图在按列分组后为其计算扩展窗口聚合。数据结构是这样的:
df = pd.DataFrame([['A',1,2015,4],['A',1,2016,5],['A',1,2017,6],['B',1,2015,10],['B',1,2016,11],['B',1,2017,12],
['A',1,2015,24],['A',1,2016,25],['A',1,2017,26],['B',1,2015,30],['B',1,2016,31],['B',1,2017,32],
['A',2,2015,4],['A',2,2016,5],['A',2,2017,6],['B',2,2015,10],['B',2,2016,11],['B',2,2017,12]],columns=['Typ','ID','Year','dat'])\
.sort_values(by=['Typ','ID','Year'])
即
Typ ID Year dat
0 A 1 2015 4
6 A 1 2015 24
1 A 1 2016 5
7 A 1 2016 25
2 A 1 2017 6
8 A 1 2017 26
12 A 2 2015 4
13 A 2 2016 5
14 A 2 2017 6
3 B 1 2015 10
9 B 1 2015 30
4 B 1 2016 11
10 B 1 2016 31
5 B 1 2017 12
11 B 1 2017 32
15 B 2 2015 10
16 B 2 2016 11
17 B 2 2017 12
我需要按 Type
和 ID
列对这个数据框进行分组,然后按 Year
计算所有观测值的扩展平均值。我写的代码是
df.groupby(by=['Typ','ID','Year']).expanding().mean().reset_index()
我期望这样的输出结果(忽略level_3
):
Typ ID Year level_3 dat
0 A 1 2015 6 14.0
1 A 1 2016 7 14.5
2 A 1 2017 8 15.0
3 A 2 2015 12 4.0
4 A 2 2016 13 4.5
5 A 2 2017 14 5.0
6 B 1 2015 9 20.0
7 B 1 2016 10 20.5
8 B 1 2017 11 21.0
9 B 2 2015 15 10.0
10 B 2 2016 16 10.5
11 B 2 2017 17 11.0
按 ['Type','ID','Year']
分组应该会为这些列的每个唯一行生成一行。相反,代码给出了这个:
Typ ID Year level_3 dat
0 A 1 2015 0 4.0
1 A 1 2015 6 14.0
2 A 1 2016 1 5.0
3 A 1 2016 7 15.0
4 A 1 2017 2 6.0
5 A 1 2017 8 16.0
6 A 2 2015 12 4.0
7 A 2 2016 13 5.0
8 A 2 2017 14 6.0
9 B 1 2015 3 10.0
10 B 1 2015 9 20.0
11 B 1 2016 4 11.0
12 B 1 2016 10 21.0
13 B 1 2017 5 12.0
14 B 1 2017 11 22.0
15 B 2 2015 15 10.0
16 B 2 2016 16 11.0
17 B 2 2017 17 12.0
expanding()
窗口函数似乎没有正确地与 groupby
一起工作,或者至少它没有按我预期的那样运行,给定逻辑。我做错了什么?
编辑:我现在知道我做错了什么,因为我期待 groupby
和 expanding
之间的不同集成。所以现在我的问题是如何使用 pandas 获得我想要的输出 - 无需任何手动迭代。
据我所知,展开均值有不同的计算方式。对于您想要的输出,我将使用 groupby
和 cumsum
的组合执行以下操作,然后在 sum
和 count
之间进行简单划分:
newDf = df.groupby(['Typ','ID','Year'])['dat'].agg(('sum', 'count')).groupby(['Typ','ID']).cumsum()
newDf['dat'] = newDf['sum']/newDf['count']
newDf = newDf.reset_index().drop(['count', 'sum'], axis = 1)
输出:
Typ ID Year dat
0 A 1 2015 14.0
1 A 1 2016 14.5
2 A 1 2017 15.0
3 A 2 2015 4.0
4 A 2 2016 4.5
5 A 2 2017 5.0
6 B 1 2015 20.0
7 B 1 2016 20.5
8 B 1 2017 21.0
9 B 2 2015 10.0
10 B 2 2016 10.5
11 B 2 2017 11.0
我有一个 pandas 数据框,我试图在按列分组后为其计算扩展窗口聚合。数据结构是这样的:
df = pd.DataFrame([['A',1,2015,4],['A',1,2016,5],['A',1,2017,6],['B',1,2015,10],['B',1,2016,11],['B',1,2017,12],
['A',1,2015,24],['A',1,2016,25],['A',1,2017,26],['B',1,2015,30],['B',1,2016,31],['B',1,2017,32],
['A',2,2015,4],['A',2,2016,5],['A',2,2017,6],['B',2,2015,10],['B',2,2016,11],['B',2,2017,12]],columns=['Typ','ID','Year','dat'])\
.sort_values(by=['Typ','ID','Year'])
即
Typ ID Year dat
0 A 1 2015 4
6 A 1 2015 24
1 A 1 2016 5
7 A 1 2016 25
2 A 1 2017 6
8 A 1 2017 26
12 A 2 2015 4
13 A 2 2016 5
14 A 2 2017 6
3 B 1 2015 10
9 B 1 2015 30
4 B 1 2016 11
10 B 1 2016 31
5 B 1 2017 12
11 B 1 2017 32
15 B 2 2015 10
16 B 2 2016 11
17 B 2 2017 12
我需要按 Type
和 ID
列对这个数据框进行分组,然后按 Year
计算所有观测值的扩展平均值。我写的代码是
df.groupby(by=['Typ','ID','Year']).expanding().mean().reset_index()
我期望这样的输出结果(忽略level_3
):
Typ ID Year level_3 dat
0 A 1 2015 6 14.0
1 A 1 2016 7 14.5
2 A 1 2017 8 15.0
3 A 2 2015 12 4.0
4 A 2 2016 13 4.5
5 A 2 2017 14 5.0
6 B 1 2015 9 20.0
7 B 1 2016 10 20.5
8 B 1 2017 11 21.0
9 B 2 2015 15 10.0
10 B 2 2016 16 10.5
11 B 2 2017 17 11.0
按 ['Type','ID','Year']
分组应该会为这些列的每个唯一行生成一行。相反,代码给出了这个:
Typ ID Year level_3 dat
0 A 1 2015 0 4.0
1 A 1 2015 6 14.0
2 A 1 2016 1 5.0
3 A 1 2016 7 15.0
4 A 1 2017 2 6.0
5 A 1 2017 8 16.0
6 A 2 2015 12 4.0
7 A 2 2016 13 5.0
8 A 2 2017 14 6.0
9 B 1 2015 3 10.0
10 B 1 2015 9 20.0
11 B 1 2016 4 11.0
12 B 1 2016 10 21.0
13 B 1 2017 5 12.0
14 B 1 2017 11 22.0
15 B 2 2015 15 10.0
16 B 2 2016 16 11.0
17 B 2 2017 17 12.0
expanding()
窗口函数似乎没有正确地与 groupby
一起工作,或者至少它没有按我预期的那样运行,给定逻辑。我做错了什么?
编辑:我现在知道我做错了什么,因为我期待 groupby
和 expanding
之间的不同集成。所以现在我的问题是如何使用 pandas 获得我想要的输出 - 无需任何手动迭代。
据我所知,展开均值有不同的计算方式。对于您想要的输出,我将使用 groupby
和 cumsum
的组合执行以下操作,然后在 sum
和 count
之间进行简单划分:
newDf = df.groupby(['Typ','ID','Year'])['dat'].agg(('sum', 'count')).groupby(['Typ','ID']).cumsum()
newDf['dat'] = newDf['sum']/newDf['count']
newDf = newDf.reset_index().drop(['count', 'sum'], axis = 1)
输出:
Typ ID Year dat
0 A 1 2015 14.0
1 A 1 2016 14.5
2 A 1 2017 15.0
3 A 2 2015 4.0
4 A 2 2016 4.5
5 A 2 2017 5.0
6 B 1 2015 20.0
7 B 1 2016 20.5
8 B 1 2017 21.0
9 B 2 2015 10.0
10 B 2 2016 10.5
11 B 2 2017 11.0