我有一个非常大的 pandas DataFrame,其中包含数千个代码以及与每个代码相关的成本(示例):
data = {'code': ['a', 'b', 'a', 'c', 'c', 'c', 'c'],
'cost': [10, 20, 100, 10, 10, 500, 10]}
df = pd.DataFrame(data)
我groupby
在级别创建一个对象code
,即:
grouped = df.groupby('code')['cost'].agg(['sum', 'mean']).apply(pd.Series)
现在我真的需要在这个grouped
DataFrame 中添加一个新列,以确定具有异常成本的代码的百分比。我最初的方法是这个外部函数(使用iqr
from scipy
):
def is_outlier(s):
# Only calculate outliers when we have more than 100 observations
if s.count() >= 100:
return np.where(s >= s.quantile(0.75) + 1.5 * iqr(s), 1, 0).mean()
else:
return np.nan
编写完这个函数后,我在上面添加is_outlier
了我的agg
论点groupby
。这不起作用,因为我正在尝试为系列is_outlier
中的每个元素评估此比率cost
:
grouped = df.groupby('code')['cost'].agg(['sum', 'mean', is_outlier]).apply(pd.Series)
我尝试使用pd.Series.where
,但它没有与np.where
. 有没有办法修改我的is_outlier
函数,该函数必须将cost
系列作为参数才能正确评估每个代码的异常值率?还是我完全偏离了道路?
更新期望结果(减去此示例的最低观察要求):
>>> grouped
code sum mean is_outlier
0 'a' 110 55 0.5
1 'b' 20 20 0
2 'c' 530 132.5 0.25
注意:为了让我计算异常值,我的样本很糟糕,因为我分别有 2、1 和 4 个观察值code
。在生产数据框中,每个代码都有成百上千的观察结果,每个观察结果都与成本相关。在上面的示例结果中,平均值的值is_outlier
意味着,对于'a'
两个观察值中的一个在异常值范围内的成本,对于'c'
四个观察值中的一个在异常值范围内的成本,等等 - 我正在尝试重新创建这个在我的函数中,通过分配 1 和 0 作为结果np.where()
并取.mean()
那个
.apply(pd.Series)
需要为了转换<pandas.core.groupby.SeriesGroupBy object> resulting from
groupbyinto a DataFrame.
的is a pandas Series with all values of
成本for each
代码, as generated from the
groupby operation (
split phase of
split-apply-combine`)