Python、Pandas:多列分组数据的百分位数

mzsu5hc0  于 2023-04-19  发布在  Python
关注(0)|答案(2)|浏览(243)

我还没能找到这个具体问题的答案。我有如下数据:

df = pd.DataFrame({'Product': ['Alpha', 'Alpha', 'Alpha', 'Alpha','Alpha', 'Beta', 'Beta', 'Beta','Beta', 'Gamma', 'Gamma', 'Gamma','Delta','Delta','Epsilon','Epsilon','Epsilon','Epsilon'],'Age': [0,1,2,5,8,0,2,3,5,1,3,2,8,5,1,5,4,2],'Quantity': [114,82,15,35,27,63,32,55,87,50,4,22,6,96,94,3,64,110]})
产品中心年龄数量
阿尔法0一百一十四
阿尔法1八十二
阿尔法十五岁
阿尔法三十五
阿尔法二十七
贝塔0六十三
贝塔三十二
贝塔五十五
贝塔八十七
伽玛1五十
伽玛
伽玛二十二
德尔塔
德尔塔九十六
厄普西隆1九十四
厄普西隆
厄普西隆六十四
厄普西隆一百一十

我要找的是年龄的任意百分位数,按产品细分,假设有数量,e,g。
| 产品中心|第70百分位数(岁)|第90百分位数(岁)|
| --------------|--------------|--------------|
| 阿尔法|0|二|
| 贝塔|五|五|
| 伽玛|二|二|
| 德尔塔|五|五|
| 厄普西隆|二|四|

rn0zuynd

rn0zuynd1#

您需要通过重复每个年龄段的数量来获得加权百分位数。您可以为此创建自定义函数并将其应用于每个组:

import numpy as np

def weighted_percentile(df, p):
    arr = np.percentile(np.repeat(df['Age'], df['Quantity']), p)
    return pd.Series(arr).rename(lambda x: f'{p[x]}th Percentile (years)')

out = (df.groupby('Product', as_index=False, sort=False)
         .apply(weighted_percentile, p=[70, 90]))

输出:

>>> out
   Product  70th Percentile (years)  90th Percentile (years)
0    Alpha                      1.0                      5.0
1     Beta                      5.0                      5.0
2    Gamma                      2.0                      2.0
3    Delta                      5.0                      5.0
4  Epsilon                      2.0                      4.0
nx7onnlm

nx7onnlm2#

这里有一个方法:

  • 重复使用np.repeat应用df.reindex,列为“数量”。
  • 按列“产品”(df.groupby)对数据进行分组,选择列“年龄”,并将.quantile与您选择的百分位数相结合:[0.7, 0.9]
  • 剩下的就是得到想要的形状:在索引level 1上使用Series.unstack,并再次应用df.reindex,这次使用来自df['Product']Series.unique)的唯一值。这将重新建立乘积值的顺序。
  • 最后,链接df.rename以重命名列,链接df.rename_axis以删除索引标签。
import pandas as pd
import numpy as np

perc = [0.7,0.9]
res = (df.reindex(np.repeat(df.index, df['Quantity']))
       .groupby('Product')['Age'].quantile(perc)
       .unstack(1)
       .reindex(df['Product'].unique())
       .rename(lambda x: f"{int(x*100)}th Percentile (years)", axis=1)
       .rename_axis(None, axis=0)
       )

res

         70th Percentile (years)  90th Percentile (years)
Alpha                        1.0                      5.0
Beta                         5.0                      5.0
Gamma                        2.0                      2.0
Delta                        5.0                      5.0
Epsilon                      2.0                      4.0

如果你想要整数,链res.astype(int)。顺便说一句,你想要的输出包含一个错误。对于“Alpha”,你有70% = 090% = 2,但它们应该分别是15

相关问题