我有一个包含“category”和“number”列的 Dataframe 。我想创建一个新列“avg_of_largest_2_from_prev_5”,该列是在按“category”分组并对前5行(不包括当前行)数值中的最高2个值取平均值后计算得出的。
np.random.seed(123)
n_rows = 10000
data = {'category': np.random.randint(1, 1000, n_rows), 'number': np.random.randint(1, n_rows, n_rows)}
df = pd.DataFrame(data)
%timeit df['avg_of_largest_2_from_prev_5'] = df.groupby('category')['number'].apply(lambda x: x.shift(1).rolling(5, min_periods=0).apply(lambda y: pd.Series(y).nlargest(2).mean()))
df = df[df['category'] == df['category'].values[0]]
df
输出:4.55 s ± 34.4 ms/循环(7次运行的平均值±标准差,每次运行1个循环)
category number avg_of_largest_2_from_prev_5
0 511 4179 NaN
392 511 2878 4179.0
1292 511 5834 3528.5
1350 511 1054 5006.5
1639 511 8673 5006.5
3145 511 8506 7253.5
4176 511 947 8589.5
4471 511 151 8589.5
4735 511 5326 8589.5
4965 511 4827 8589.5
5046 511 9792 6916.0
5316 511 3772 7559.0
5535 511 1095 7559.0
5722 511 5619 7559.0
5732 511 700 7705.5
6825 511 1156 7705.5
6877 511 7240 4695.5
8100 511 2381 6429.5
8398 511 2376 6429.5
这个操作需要36秒处理10 k行和1 k个类别。当我在1 m+行的 Dataframe 中尝试这个操作时,它需要大约8分钟。我认为应该有一个更快的方法来完成我正在尝试做的事情,我将感谢任何建议。
2条答案
按热度按时间ni65a41a1#
另一种解决方案是使用Polars(https://www.pola.rs/)代替Pandas。
在我的测试中,Pandas功能需要5.33秒,而Polars功能需要30.1毫秒,因此快了178倍。
您可以使用
pip install polars
安装Polars函数如下:
5rgfhyps2#
您的样品
速度提升
一个二个一个一个
与样品相比,速度提高了
3.7%
。对于所选的示例,我们无法真正看到
agg
函数与apply
函数相比的效率,但另一方面,如果我们将类别数量减少到10,并相应地将更多行转移到agg
函数进行处理,我们会意识到变化非常显著。在本例中,改进为
6%
现在,我测试以下参数:
并通过
9.5%
的改进获得这些结果:结论
数据越多,类别越少,第二种方法的性能就越高