我在将groupby_object.agg()方法与要更改输入参数的函数一起使用时遇到问题。是否有可用的函数名称.agg()接受的资源,以及如何将参数传递给它们?
请参阅以下示例:
import pandas as pd
import numpy as np
df = pd.DataFrame({'numbers': [1, 2, 3, 2, 1, 3],
'colors': ['red', 'white', 'blue', 'red', 'white', np.nan],
'weight': [10, 10, 20, 5, 10, 20]})
df['colors'].nunique() # Returns 3 as NaN is not counted
df['colors'].nunique(dropna=False) # Returns 4 as NaN is counted
当我为groupby
颜色上色时,如何通过dropna=False
函数传递参数?
df.groupby('numbers').agg({'colors': 'nunique', 'weight': 'sum'})
尽管pandas
具有与dict和NamedAggs聚合的漂亮语法,但它们可能会付出巨大的效率成本。的原因是因为,而不是使用内置的GROUPBY方法,该方法被优化和/或在用Cython实现,任何.agg(lambda x: ...)
或.apply(lambda x: ...)
将要采取慢得多的路径。
这意味着您应该坚持可以直接引用或通过别名引用的内置插件。只有在万不得已的情况下,您才可以尝试使用lambda
:
在这种特殊情况下使用
df.groupby('numbers')[['colors']].agg('nunique', dropna=False)
避免
df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False)})
此示例表明,尽管输出相等,并且看似很小的变化,但在性能方面会产生巨大的后果,尤其是当组的数量变大时。
import perfplot
import pandas as pd
import numpy as np
def built_in(df):
return df.groupby('numbers')[['colors']].agg('nunique', dropna=False)
def apply(df):
return df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False)})
perfplot.show(
setup=lambda n: pd.DataFrame({'numbers': np.random.randint(0, n//10+1, n),
'colors': np.random.choice([np.NaN] + [*range(100)])}),
kernels=[
lambda df: built_in(df),
lambda df: apply(df)],
labels=['Built-In', 'Apply'],
n_range=[2 ** k for k in range(1, 20)],
equality_check=np.allclose,
xlabel='~N Groups'
)
.groupby()
groupby的部分实际上并没有做那么多。它只是确保映射是正确的。因此,尽管不直观,但与内置函数单独聚合并最终将结果连接起来仍然比使用lambda进行更简单的命令聚合要快得多。
这也是一个想要sum
权重列的示例,我们可以看到,尽管需要手动加入,但拆分速度仍然快得多
def built_in(df):
return pd.concat([df.groupby('numbers')[['colors']].agg('nunique', dropna=False),
df.groupby('numbers')[['weight']].sum()], axis=1)
def apply(df):
return df.groupby('numbers').agg({'colors': lambda x: x.nunique(dropna=False),
'weight': 'sum'})
perfplot.show(
setup=lambda n: pd.DataFrame({'numbers': np.random.randint(0, n//10+1, n),
'colors': np.random.choice([np.NaN] + [*range(100)]),
'weight': np.random.normal(0,1,n)}),
kernels=[
lambda df: built_in(df),
lambda df: apply(df)],
labels=['Built-In', 'Apply'],
n_range=[2 ** k for k in range(1, 20)],
equality_check=np.allclose,
xlabel='~N Groups'
)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句