将百分位数传递给pandas agg函数

111

我希望能够像其他numpy统计函数一样,通过pandas的agg()函数使用numpy的percentile()函数。

目前,我的数据框如下所示:

AGGREGATE   MY_COLUMN
A           10
A           12
B           5
B           9
A           84
B           22

我的代码看起来像这样:

grouped = dataframe.groupby('AGGREGATE')
column = grouped['MY_COLUMN']
column.agg([np.sum, np.mean, np.std, np.median, np.var, np.min, np.max])

上述代码可以工作,但我想实现类似于以下的操作:

column.agg([np.sum, np.mean, np.percentile(50), np.percentile(95)])

即,指定从agg()返回的各种百分位数。

应该如何做?


16个回答

6

仅仅为了提供一个更加通用的解决方案。假设你有一个只有一列需要分组的数据框:

df = pd.DataFrame((('A',10),('A',12),('B',5),('B',9),('A',84),('B',22)), 
                    columns=['My_KEY', 'MY_COL1'])

通过使用匿名(lambda)函数的列表,可以聚合和计算基本上任何描述性指标,例如:

df.groupby(['My_KEY']).agg( [np.sum, np.mean, lambda x: np.percentile(x, q=25)] )

然而,如果你需要对多列进行聚合,你必须调用一个非匿名函数或显式地调用列:

df = pd.DataFrame((('A',10,3),('A',12,4),('B',5,6),('B',9,3),('A',84,2),('B',22,1)), 
                    columns=['My_KEY', 'MY_COL1', 'MY_COL2'])

# non-anonymous function
def percentil25 (x): 
    return np.percentile(x, q=25)

# type 1: call for both columns 
df.groupby(['My_KEY']).agg( [np.sum, np.mean, percentil25 ]  )

# type 2: call each column separately
df.groupby(['My_KEY']).agg( {'MY_COL1': [np.sum, np.mean, lambda x: np.percentile(x, q=25)],
                             'MY_COL2': np.size})

4

这可以提供一些自定义:

list_statistics = ['count','mean','min',lambda x: np.percentile(x,q=25),'max',lambda x: np.percentile(x,q=75)]
cols_to_rename = {'<lambda_0>':'P25','<lambda_1>':'P75'}
df_out.groupby('Country').agg(list_statistics).rename(columns=cols_to_rename)

0

如果您有一个包含多个列的数据框,但只想获取其中一列的分位数:

df.groupby("AGGREGATE")['MY_COLUMN'].quantile([0, 0.25, 0.5, 0.75, 0.95, 1])

如果你想要一个一级数据框,你可以添加:

df.groupby("AGGREGATE")['MY_COLUMN'].quantile([0, 0.25, 0.5, 0.75, 0.95, 1]).reset_index()

0

多个函数可以按以下方式调用:

import pandas as pd

import numpy as np

import random

C = ['Ram', 'Ram', 'Shyam', 'Shyam', 'Mahima', 'Ram', 'Ram', 'Shyam', 'Shyam', 'Mahima']

A = [ random.randint(0,100) for i in range(10) ]

B = [ random.randint(0,100) for i in range(10) ]

df = pd.DataFrame({ 'field_A': A, 'field_B': B, 'field_C': C })

print(df)

d = df.groupby('field_C')['field_A'].describe()[['mean', 'count', '25%', '50%', '75%']]
print(d)

我无法在这里调用中位数函数,但能够使用其他函数。


1
这句话调用了所有函数,但只选择了其中几个。这样做会影响性能,这也是你使用 agg 而不是 describe 的原因。 - Sebastian Wozny
@SebastianWozny,也许您可以更新一下您的评论,谈谈在处理大数据时您推荐哪种解决方案。 - Areza

0

您可以定义简单的 Lambda 函数

my_quant = lambda _q: lambda _data:_data.quantile(_q)

使用所需的分位数

df.aggregate([my_quant(0.1),my_quant(0.3),'median',my_quant(0.7)]

** 如果你想保留聚合名称而不重命名索引,你可以创建lambda creator并设置函数名称。
def lambda_creator(func,name):
    func.__name__ = name
    return func

my_quant = lambda _q: lambda_creator(lambda _data: _data.quantile(_q),f'quantile_{_q}')

0

使用数据框的groupby和agg函数获取Q1结果,以下是推荐的代码。

import numpy as np 
df.groupby(['col1','col2']).agg(quantile_columns = ('column_name', lambda x: np.percentile(x, q=25)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接