好吧,所以我认为你正在寻找的答案是 - 我们不这样做,因为 python 中的矢量化
考虑下面的代码。
现在本质上 - python 通常被优化为以向量化的方式执行某些数学运算(采取numpy
or pandas
例如) - 这意味着 - 将其应用于整个向量比将其分解为块然后执行它更快。
So e.g. df["A"].mul(df["B"])
将比以下更快:df.apply(lambda X: X["A"]*X["B"], axis=0)
。分组也是如此——这样更具可扩展性。
尝试下面的代码 - 这本质上就是你所指的 - 所以在之前和之后进行操作groupby(...)
。即使您实现了额外的列,矢量化解决方案的扩展速度也非常快 - 处理的行越多,您将看到的差异就越大。
Edit
我在分组数据上添加了矢量化解决方案,所以我们有:
(1) 我们分组,我们逐行懒惰地评估
(2)我们以向量化的方式处理完整的df,我们应用内置聚合函数进行分组
(3)我们分组,我们以向量化的方式处理分组,按组,我们做聚合函数
本质上 - 从结果中我们看到分解成块会减慢处理速度,无论是按组还是按记录 - 因此矢量化解决方案比我们可以在其上应用的任何类型的自定义解决方案都具有更好的扩展性。
import pandas as pd
import numpy as np
import time
x=np.random.randint(1,9,(3000,5))
df=pd.DataFrame(x, columns=[f"column{l}" for l in list("ABCDE")])
df["cat"]=np.random.choice([f"key{l}" for l in list("ABCDEFG")], size=3000)
df2=df3=df
#print(df)
s=time.time()
df.groupby("cat").apply(lambda z: np.prod(z.values, axis=1).mean()).pipe(print)
e=time.time()-s
print(f"method 1: {e} s")
s=time.time()
df2["prod"]=np.prod(df[[f"column{l}" for l in list("ABCDE")]], axis=1)
df2.groupby("cat")["prod"].mean().pipe(print)
e=time.time()-s
print(f"method 2: {e} s")
s=time.time()
df3=list(map(lambda x: (x[0], np.prod(x[1][[f"column{l}" for l in list("ABCDE")]], axis=1).mean()), df3.groupby("cat")))
print(df3)
e=time.time()-s
print(f"method 3: {e} s")