我有一个关于使用用户定义的函数聚合熊猫数据框的问题。如果我有一个数据框并在有或没有groupby的情况下运行agg,则在使用内置函数时会汇总结果。另一方面,如果i使用自定义函数,则在使用groupby时将按预期工作。如果未使用groupby,则不会进行聚合。有没有聚集而不使用自定义功能的方法?我知道一个可以只添加一个虚拟变量,但这不是首选的解决方案。测试1-3按预期工作,但未测试4。
OnSettingValueUpdated
答案 0 :(得分:1)
尝试使用.apply()
:
df.apply(CoV, axis=0)
这也适用于我:
test4 = df.agg(CoV, axis=0)
您将获得一个带有应用函数的标量结果的数据框:
a b c
CoV 0.585977 0.584645 0.406688
然后仅分割您需要的系列。
假设:您要在没有分组依据的不同列上应用单个自定义标量函数(从系列到标量)。
编辑:如果您想组合多个功能,则可以做的另一件事是将所有功能都显示为功能的输出(返回pd.Series
)。例如,您可以将自定义函数重写为:
def myfunc(_s):
return pd.Series({'mean': _s.mean(),
'std': _s.std(),
'CoV' : np.std(_s)/np.mean(_s)})
然后使用.apply()
运行此命令将产生多个结果。
df.apply(myfunc)
现在将给出:
a b c
mean 0.495922 0.511350 2.011000
std 0.290744 0.299108 0.818259
CoV 0.585977 0.584645 0.406688
在此处查看更多信息: Pandas how to apply multiple functions to dataframe
答案 1 :(得分:1)
这将为您提供所需的结果:
df.assign(k=1).groupby('k')['a'].apply(CoV).reset_index(drop=True)
因此,您assign k
仅用于groupby
,然后通过reseting
和droping
索引将其删除。
答案 2 :(得分:0)
这里的答案都没有解决为什么失败。如果您研究熊猫代码,则将UDF传递到df.agg
时,每列的Series对象将传递到UDF。
在您的情况下,使用字典选择Series对象(一列),然后将UDF传递到Series对象的Series.agg
函数。由于它不是已知函数(例如字符串'mean'
),因此最终将其传递给Series.apply
,后者将函数映射到Series对象中的每个值。这是您看到的结果。
幸运的是,将UDF传递到Series.apply
是在try/except
块中进行的。如果使用Series.apply(func)
无法正常工作,它将交换为通过func(Series)
将Series对象传递给函数。如果传递的对象不是Series或DataFrame,则可以使用它来修改代码以引发错误。
def CoV(_s):
if not isinstance(_s, (pd.Series, pd.DataFrame, np.array)):
raise TypeError()
return pd.Series({'CoV' : np.std(_s)/np.mean(_s)})
现在将其传递给.agg
即可正常工作。这是一个很棘手的解决方法,但是可以。
df.agg({'a': CoV})
# returns:
a
CoV 0.584645
编辑:
要使其与其他功能(例如'mean'
)一起使用,很不幸,您也必须将它们作为UDF传递。更糟糕的是,UDF的结果累积与内置函数不同。熊猫只需将它们与分层的列索引水平堆叠即可。简单的stack
和reset_index
可以解决此问题。
def check_input(fn):
def wrapper(_s, *args, **kwargs):
if not isinstance(_s, (pd.Series, pd.DataFrame, np.array)):
raise TypeError()
return fn(_s, *args, **kwargs)
wrapper.__name__ = fn.__name__
return wrapper
@check_input
def Mean(_s):
return pd.Series({'Mean': np.mean(_s)})
@check_input
def CoV(_s):
return pd.Series({'CoV' : np.std(_s)/np.mean(_s)})
df.agg({'a': [CoV, Mean], 'c': Mean}).stack().reset_index(level=-1, drop=True)
# returns:
a c
CoV 0.584645 NaN
Mean 0.511350 2.011