Skip to main content
 首页 » 编程设计

python之使用单独的自定义容器(阈值)对 Pandas 列进行分类

2025年05月04日12Leo_wl

我有一个 dataframe,其中一些数值存储在 "value" 列中,伴随着它们各自的分类阈值(在本例中为警告级别),存储在其他列中(在我的例子中,“低”、“中”、“高”):

     value    low  middle    high 
0   179.69  17.42   88.87  239.85 
1     2.58  17.81   93.37  236.58 
2     1.21   0.05    0.01    0.91 
3     1.66   0.20    0.32    4.57 
4     3.54   0.04    0.04    0.71 
5     5.97   0.16    0.17    2.55 
6     5.39   0.86    1.62    9.01 
7     1.20   0.03    0.01    0.31 
8     3.19   0.08    0.01    0.45 
9     0.02   0.03    0.01    0.10 
10    3.98   0.18    0.05    0.83 
11  134.51  78.63  136.86  478.27 
12  254.53  83.73  146.33  486.65 
13   15.36  86.07   13.74  185.16 
14   85.10  86.12   13.74  185.16 
15   15.12   1.37    6.09   30.12 

我想知道每个值属于哪个类别(例如,第一个值是middle,第二个是below_low,因为它小于它的任何阈值,第三个将是高,......你明白了)。所以这是预期的输出:

     value    low  middle    high   category 
0   179.69  17.42   88.87  239.85     middle 
1     2.58  17.81   93.37  236.58  below_low 
2     1.21   0.05    0.01    0.91       high 
3     1.66   0.20    0.32    4.57     middle 
4     3.54   0.04    0.04    0.71       high 
5     5.97   0.16    0.17    2.55       high 
6     5.39   0.86    1.62    9.01     middle 
7     1.20   0.03    0.01    0.31       high 
8     3.19   0.08    0.01    0.45       high 
9     0.02   0.03    0.01    0.10     middle 
10    3.98   0.18    0.05    0.83       high 
11  134.51  78.63  136.86  478.27        low 
12  254.53  83.73  146.33  486.65     middle 
13   15.36  86.07   13.74  185.16     middle 
14   85.10  86.12   13.74  185.16     middle 
15   15.12   1.37    6.09   30.12     middle 

到目前为止,我使用这种逐行“手动”检查的丑陋程序,停在第一个类别(从高到低),大于当前值:

df["category"]="below_low"     
for i in df.index: 
    for cat in ["high","middle","low"]: 
        if df.loc[i,"value"]>df.loc[i,cat]: 
            df.loc[i,"category"]=cat 
            break 

我知道 pd.cut() 方法,但我只知道如何将它与预定义的通用阈值列表一起使用。有人能告诉我我错过了什么吗?

请您参考如下方法:

您可以使用:

  • 删除列值
  • 与lt比较(少于)
  • 更改列的顺序
  • 累积总和列 - 首先 True 得到 1
  • 通过eq 与1 比较

mask = df.drop('value',axis=1) 
         .lt(df['value'], axis=0) 
         .reindex(columns=['high','middle','low']) 
         .cumsum(axis=1) 
         .eq(1) 

如果 high、middle 和 low 列中的所有值都是 False,则需要一些正确性。我使用反转的 mask 和 all 创建新列。

mask['below_low'] = (~mask).all(axis=1) 
print (mask) 
     high middle    low below_low 
0    True  False  False     False 
1   False  False  False      True 
2    True  False  False     False 
3   False   True  False     False 
4    True  False  False     False 
5    True  False  False     False 
6   False   True  False     False 
7    True  False  False     False 
8    True  False  False     False 
9   False   True   True     False 
10   True  False  False     False 
11  False  False   True     False 
12  False   True  False     False 
13  False   True   True     False 
14  False   True   True     False 
15  False   True  False     False 

上次通话 DataFrame.idxmax :

df['category'] = mask.idxmax(axis=1) 
print (df) 
     value    low  middle    high   category 
0   179.69  17.42   88.87  239.85       high 
1     2.58  17.81   93.37  236.58  below_low 
2     1.21   0.05    0.01    0.91       high 
3     1.66   0.20    0.32    4.57     middle 
4     3.54   0.04    0.04    0.71       high 
5     5.97   0.16    0.17    2.55       high 
6     5.39   0.86    1.62    9.01     middle 
7     1.20   0.03    0.01    0.31       high 
8     3.19   0.08    0.01    0.45       high 
9     0.02   0.03    0.01    0.10     middle 
10    3.98   0.18    0.05    0.83       high 
11  134.51  78.63  136.86  478.27        low 
12  254.53  83.73  146.33  486.65     middle 
13   15.36  86.07   13.74  185.16     middle 
14   85.10  86.12   13.74  185.16     middle 
15   15.12   1.37    6.09   30.12     middle 

具有多个 numpy.where 的解决方案正如指出的那样Paul H :

df['category'] = np.where(df['high'] < df['value'], 'high',  
                 np.where(df['middle'] < df['value'], 'medium', 
                 np.where(df['low'] < df['value'], 'low', 'below_low'))) 
 
print (df) 
     value    low  middle    high   category 
0   179.69  17.42   88.87  239.85       high 
1     2.58  17.81   93.37  236.58  below_low 
2     1.21   0.05    0.01    0.91       high 
3     1.66   0.20    0.32    4.57     medium 
4     3.54   0.04    0.04    0.71       high 
5     5.97   0.16    0.17    2.55       high 
6     5.39   0.86    1.62    9.01     medium 
7     1.20   0.03    0.01    0.31       high 
8     3.19   0.08    0.01    0.45       high 
9     0.02   0.03    0.01    0.10     medium 
10    3.98   0.18    0.05    0.83       high 
11  134.51  78.63  136.86  478.27        low 
12  254.53  83.73  146.33  486.65     medium 
13   15.36  86.07   13.74  185.16     medium 
14   85.10  86.12   13.74  185.16     medium 
15   15.12   1.37    6.09   30.12     medium