Pandas/Python中相同值的多个分位数标签

xytpbqjk  于 2023-01-24  发布在  Python
关注(0)|答案(2)|浏览(145)

我有一个指标,我正尝试创建新列,其中包含描述每个指标值所属分位数的标签。但是,我发现,对于同一个指标值,我收到多个分位数标签,而我希望它们只收到一个。
我有一个类似这样的指标:
| 公制|
| - ------|
| 5.0 |
| 5.0 |
| 6.0 |
| 5.0 |
| 钠氮|
| 5.0 |
| 5.0 |
| 2.0 |
| 6.0 |
| 3.0 |
| 钠氮|
| 2.0 |
| 5.0 |
| 5.0 |
| 5.0 |
| 2.0 |
我想创建新的列,其中包含一个分位数范围的分位数标签。这就是我正在做的:

var_metric = ['Metric']

# Quantile range I am interested in creating labels for
quantiles_list = [2, 3, 4, 5]

# Quantile labels
quantile_2_labels = ['Quantile_2_1','Quantile_2_2']
quantile_3_labels = ['Quantile_3_1','Quantile_3_2','Quantile_3_3']
quantile_4_labels = ['Quantile_4_1','Quantile_4_2','Quantile_4_3','Quantile_4_4']
quantile_5_labels = ['Quantile_5_1','Quantile_5_2','Quantile_5_3','Quantile_5_4','Quantile_5_5']
quantiles_labels_list = [quantile_2_labels, quantile_3_labels, quantile_4_labels, quantile_5_labels]

# Loops for creating label columns
for metric in var_metric:
        for quantile, labels in zip(quantiles_list, quantiles_labels_list):
                df[f'{metric}_Quantile_{quantile}'] = pd.qcut(df[metric].astype('Int64').rank(method='first'), q=quantile, labels=labels, retbins=False)

结果如下所示:
| 公制|度量_分位数_2|度量_分位数_3|度量分位数4|度量_分位数_5|
| - ------|- ------|- ------|- ------|- ------|
| 2.0 |分位数_2_1|分位数_3_1|分位数_4_1|分位数_5_1|
| 5.0 |分位数_2_1|分位数_3_2|分位数_4_2|分位数_5_2|
| 5.0 |分位数_2_1|分位数_3_2|分位数_4_2|分位数_5_3|
| 6.0 |分位数_2_2|分位数_3_3|分位数_4_4|分位数_5_5|
| 5.0 |分位数_2_1|分位数_3_2|分位数_4_2|分位数_5_3|
| 钠氮|钠氮|钠氮|钠氮|钠氮|
| 5.0 |分位数_2_2|分位数_3_2|分位数_4_3|分位数_5_3|
| 5.0 |分位数_2_2|分位数_3_2|分位数_4_3|分位数_5_4|
| 2.0 |分位数_2_1|分位数_3_1|分位数_4_1|分位数_5_1|
| 6.0 |分位数_2_2|分位数_3_3|分位数_4_4|分位数_5_5|
| 3.0 |分位数_2_1|分位数_3_1|分位数_4_2|分位数_5_2|
| 钠氮|钠氮|钠氮|钠氮|钠氮|
| 2.0 |分位数_2_1|分位数_3_1|分位数_4_1|分位数_5_1|
| 5.0 |分位数_2_2|分位数_3_3|分位数_4_3|分位数_5_4|
| 5.0 |分位数_2_2|分位数_3_3|分位数_4_4|分位数_5_4|
| 5.0 |分位数_2_2|分位数_3_3|分位数_4_4|分位数_5_5|
| 2.0 |分位数_2_1|分位数_3_1|分位数_4_1|分位数_5_2|
Metric_Quantile_2列为例,我希望Metric = 5.0在所有情况下都得到相同的标签,但是在第二列中可以看到5.0值的标签在Quantile_2_1Quantile_2_2之间移动,知道为什么吗?
谢谢!

yiytaume

yiytaume1#

你不能期望你的代码产生正确的结果,因为你没有在df['Metric']上应用qcut,而是在df['Metric'].rank(...)上应用qcut,这不是一回事:

>>> pd.concat([df[metric], df[metric].rank(method='first')], keys=['Metric', 'Rank'], axis=1)

    Metric  Rank
0      5.0   5.0
1      5.0   6.0
2      6.0  13.0
3      5.0   7.0
4      NaN   NaN
5      5.0   8.0
6      5.0   9.0
7      2.0   1.0
8      6.0  14.0
9      3.0   4.0
10     NaN   NaN
11     2.0   2.0
12     5.0  10.0
13     5.0  11.0
14     5.0  12.0
15     2.0   3.0

有效措施:

>>> pd.concat([df, pd.qcut(df[metric], q=quantile, labels=labels, retbins=False)], axis=1)

   Metric        Metric
0     5.0  Quantile_2_1  # OK
1     5.0  Quantile_2_1  # OK
2     6.0  Quantile_2_2
3     5.0  Quantile_2_1  # OK
4     NaN           NaN
5     5.0  Quantile_2_1  # OK
6     5.0  Quantile_2_1  # OK
7     2.0  Quantile_2_1
8     6.0  Quantile_2_2
9     3.0  Quantile_2_1
10    NaN           NaN
11    2.0  Quantile_2_1
12    5.0  Quantile_2_1  # OK
13    5.0  Quantile_2_1  # OK
14    5.0  Quantile_2_1  # OK
15    2.0  Quantile_2_1

什么不起作用:

>>> pd.concat([df, pd.qcut(df[metric].rank(method='first'), q=quantile, labels=labels, retbins=False)], axis=1)

   Metric        Metric
0     5.0  Quantile_2_1  # OK but lucky, rank=5, first quantile
1     5.0  Quantile_2_1  # OK but lucky, rank=6, first quantile
2     6.0  Quantile_2_2
3     5.0  Quantile_2_1  # OK but lucky, rank=7, first quantile
4     NaN           NaN
5     5.0  Quantile_2_2  # KO, rank=8, second quantile
6     5.0  Quantile_2_2  # KO, rank=9, second quantile
7     2.0  Quantile_2_1
8     6.0  Quantile_2_2
9     3.0  Quantile_2_1
10    NaN           NaN
11    2.0  Quantile_2_1
12    5.0  Quantile_2_2  # KO, rank=10, second quantile
13    5.0  Quantile_2_2  # KO, rank=11, second quantile
14    5.0  Quantile_2_2  # KO, rank=12, second quantile
15    2.0  Quantile_2_1
zbwhf8kr

zbwhf8kr2#

问题在于pd.qcut,它试图将相同数量的观测放入每个分位数条柱中。但是,如果同一值多次出现,迫使某些条柱包含的观测数多于其他条柱,则它不知道如何处理。
这篇文章分解了你在这种情况下的选择:How to qcut with non unique bin edges?
最后,我决定改用pd.cut,它取指标值域的最小值和最大值,然后将值域分割成大小相等的区间,再将观测值放入这些区间,结果是每个区间的观测值数量不同。
这是我最后的forloop:

for metric in var_metric:
        for quantile, labels in zip(quantiles_list, quantiles_labels_list):
                df[f'{metric}_Quantile_{quantile}'] = pd.cut(df[metric].astype('Int64'), bins=quantile, labels=labels, retbins=False)

我希望这是清楚的。谢谢大家的帮助!

相关问题