我有一个函数希望应用于pandas DataFrame的子集,因此该函数是在同一组的所有行(直到当前行)上计算的,即使用groupby
然后使用{ {1}}。
例如,此数据框:
expanding
即
df = pd.DataFrame.from_dict(
{
'group': ['A','A','A','B','B','B'],
'time': [1,2,3,1,2,3],
'x1': [10,40,30,100,200,300],
'x2': [1,0,1,2,0,3]
}).sort_values('time')
和此功能,例如:
group time x1 x2
0 A 1 10 1
3 B 1 100 2
1 A 2 40 2
4 B 2 200 0
2 A 3 30 1
5 B 3 300 3
[为清晰起见,根据jezrael的反馈进行了编辑:我的实际功能更加复杂,因此无法轻松分解为该任务的组件。这个简单的功能仅适用于MCVE。]
我想做类似的事情:
def foo(_df):
return _df['x1'].max() * _df['x2'].iloc[-1]
要获得此结果:
df['foo_result'] = df.groupby('group').expanding().apply(foo, raw=False)
问题是,运行 group time x1 x2 foo_result
0 A 1 10 1 10
3 B 1 100 2 200
1 A 2 40 2 80
4 B 2 200 0 0
2 A 3 30 1 40
5 B 3 300 3 900
会导致df.groupby('group').expanding().apply(foo, raw=False)
。
是否有正确的方法来运行此程序,或者在KeyError: 'x1'
中不将我的功能分解为组件而无法运行?
答案 0 :(得分:1)
可能的解决方案是使expanding
成为函数的一部分,并使用GroupBy.apply
:
def foo1(_df):
return _df['x1'].expanding().max() * _df['x2'].expanding().apply(lambda x: x[-1], raw=True)
df['foo_result'] = df.groupby('group').apply(foo1).reset_index(level=0, drop=True)
print (df)
group time x1 x2 foo_result
0 A 1 10 1 10.0
3 B 1 100 2 200.0
1 A 2 40 2 80.0
4 B 2 200 0 0.0
2 A 3 30 1 40.0
5 B 3 300 3 900.0
这不是直接将数据框功能应用于expanding
数据框的问题的直接解决方案,但是它实现了相同的功能。
答案 1 :(得分:0)
显然无法在expanding
窗口上应用数据框函数(至少对于非熊猫版本0.23.0),如将print
语句插入函数中所看到的那样。
在给定的DataFrame上运行df.groupby('group').expanding().apply(lambda x: bool(print(x)) , raw=False)
(其中bool
周围的print
只是为了获得有效的返回值)返回:
0 1.0
dtype: float64
0 1.0
1 2.0
dtype: float64
0 1.0
1 2.0
2 3.0
dtype: float64
0 10.0
dtype: float64
0 10.0
1 40.0
dtype: float64
0 10.0
1 40.0
2 30.0
dtype: float64
(依此类推-并且当然还会在每个单元格中返回一个带有“ 0.0”的数据框)。
这表明expanding
窗口是逐列工作的(我们看到,首先打印扩展的time
系列,然后打印x1
,依此类推),并且不能真正在数据框上使用-因此无法将数据框功能应用于该数据框。
因此,要获得所获得的功能,必须将expanding
放在dataframe函数中,就像在接受的答案中一样。