如何做比 pandas DataFrame 合并更好的 than/less?

How to do greater than/less than binning with pandas DataFrame?

我有一个 pandas DataFrame 如下:

import pandas as pd
import numpy as np

data = {"first_column": ["item1", "item2", "item3", "item4", "item5", "item6", "item7"],
        "second_column": ["cat1", "cat1", "cat1", "cat2", "cat2", "cat2", "cat2"],
        "third_column": [5, 1, 8, 3, 731, 189, 9]}

df = pd.DataFrame(data)

df
     first_column second_column  third_column
0        item1          cat1             5
1        item2          cat1             1
2        item3          cat1             8
3        item4          cat2             3
4        item5          cat2           731
5        item6          cat2           189
6        item7          cat2             9

现在,假设我想使用 pandas.cut() 创建第四列来显示第三列的分类。这里,我在每一行标注third_column中的元素是否小于等于十,<=10

df["less_than_ten"]= pd.cut(df.third_column, [-np.inf, 10, np.inf], labels=(1,0))

现在生成的数据框是:

      first_column second_column  third_column less_than_ten
0        item1          cat1             5             1
1        item2          cat1             1             1
2        item3          cat1             8             1
3        item4          cat2             3             1
4        item5          cat2           731             0
5        item6          cat2           189             0
6        item7          cat2             9             1

问题:请注意第二列 second_column,类别为 cat1cat2。我将如何使用 pandas.cut() 根据 second_column 中的 "class" 对这些值进行重新分类?

更重要的是,假设我想要更复杂的间隔,例如小于或等于 500 le(500) 且大于或等于 20 ge(20)?这将如何完成?在这种情况下,应该有一个 1 标记为分组:

      first_column second_column  third_column less_than_ten
0        item1          cat1             5             1
1        item2          cat1             1             1
2        item3          cat1             8             1
3        item4          cat2             3             1
4        item5          cat2           731             0
5        item6          cat2           189             1
6        item7          cat2             9             1

在这种情况下我不会使用 pd.cut:

df['less_than_ten'] = df.third_column.le(10).astype(np.uint8)
df.loc[df.second_column=='cat2','less_than_ten'] = \
    df.loc[df.second_column=='cat2','third_column'].le(10).astype(np.uint8) + 2

结果:

In [99]: df
Out[99]:
  first_column second_column  third_column  less_than_ten
0        item1          cat1             5              1
1        item2          cat1             1              1
2        item3          cat1             8              1
3        item4          cat2             3              3
4        item5          cat2           731              2
5        item6          cat2           189              2
6        item7          cat2             9              3

虽然我完全理解我提出的解决方案看起来像黑客并且给出的数字与您的不同,但我仍然在这里提供它:

df['less_than_ten'] = (df.second_column=='cat1').astype(int) +\
                      (df.third_column<10).astype(int)  
#  first_column second_column  third_column  less_than_ten
#0        item1          cat1             5              2
#1        item2          cat1             1              2
#2        item3          cat1             8              2
#3        item4          cat2             3              1
#4        item5          cat2           731              0
#5        item6          cat2           189              0
#6        item7          cat2             9              1

括号中的条件可以任意复杂,只要是布尔值即可(True/False)。