使用Pandas进行二维分箱

5

我有两组特征想要进行分组(分类),然后合并成一个新的特征。这与在地图上将坐标分类为网格类似。

问题在于,这些特征的分布不均匀,我想在对两个特征/坐标进行分组时使用分位数(例如用pandas.qcut())。

是否有更好的方法来处理,而不是对两个特征都进行qcut(),然后连接结果标签?


我想不出其他更好的方法了。这似乎是绝对适当的方式。唯一更好的事情就是有一个内置函数来完成它。 - piRSquared
我错了...有些东西我更喜欢 - piRSquared
我正在认真等待... - Reuben L.
现在将它们组合起来...不要太激动,它仅是相同想法的扩展。 - piRSquared
1个回答

10

创建笛卡尔积分类。

考虑数据框 df

df = pd.DataFrame(dict(A=np.random.rand(20), B=np.random.rand(20)))

           A         B
0   0.538186  0.038985
1   0.185523  0.438329
2   0.652151  0.067359
3   0.746060  0.774688
4   0.373741  0.009526
5   0.603536  0.149733
6   0.775801  0.585309
7   0.091238  0.811828
8   0.504035  0.639003
9   0.671320  0.132974
10  0.619939  0.883372
11  0.301644  0.882258
12  0.956463  0.391942
13  0.702457  0.099619
14  0.367810  0.071612
15  0.454935  0.651631
16  0.882029  0.015642
17  0.880251  0.348386
18  0.496250  0.606346
19  0.805688  0.401578

我们可以使用 pd.qcut 创建新的分类变量。

d1 = df.assign(
    A_cut=pd.qcut(df.A, 2, labels=[1, 2]),
    B_cut=pd.qcut(df.B, 2, labels=list('ab'))
)

           A         B A_cut B_cut
0   0.538186  0.038985     1     a
1   0.185523  0.438329     1     b
2   0.652151  0.067359     2     a
3   0.746060  0.774688     2     b
4   0.373741  0.009526     1     a
5   0.603536  0.149733     1     a
6   0.775801  0.585309     2     b
7   0.091238  0.811828     1     b
8   0.504035  0.639003     1     b
9   0.671320  0.132974     2     a
10  0.619939  0.883372     2     b
11  0.301644  0.882258     1     b
12  0.956463  0.391942     2     a
13  0.702457  0.099619     2     a
14  0.367810  0.071612     1     a
15  0.454935  0.651631     1     b
16  0.882029  0.015642     2     a
17  0.880251  0.348386     2     a
18  0.496250  0.606346     1     b
19  0.805688  0.401578     2     b

您可以使用元组创建笛卡尔积范畴

d2 = d1.assign(cartesian=pd.Categorical(d1.filter(regex='_cut').apply(tuple, 1)))
print(d2)

           A         B A_cut B_cut cartesian
0   0.538186  0.038985     1     a    (1, a)
1   0.185523  0.438329     1     b    (1, b)
2   0.652151  0.067359     2     a    (2, a)
3   0.746060  0.774688     2     b    (2, b)
4   0.373741  0.009526     1     a    (1, a)
5   0.603536  0.149733     1     a    (1, a)
6   0.775801  0.585309     2     b    (2, b)
7   0.091238  0.811828     1     b    (1, b)
8   0.504035  0.639003     1     b    (1, b)
9   0.671320  0.132974     2     a    (2, a)
10  0.619939  0.883372     2     b    (2, b)
11  0.301644  0.882258     1     b    (1, b)
12  0.956463  0.391942     2     a    (2, a)
13  0.702457  0.099619     2     a    (2, a)
14  0.367810  0.071612     1     a    (1, a)
15  0.454935  0.651631     1     b    (1, b)
16  0.882029  0.015642     2     a    (2, a)
17  0.880251  0.348386     2     a    (2, a)
18  0.496250  0.606346     1     b    (1, b)
19  0.805688  0.401578     2     b    (2, b)
如果你愿意的话,甚至可以为它们声明一个顺序。

看起来很不错。谢谢!如果没有其他挑战者出现,我会在合理的时间内接受这个答案。 - Reuben L.
谢谢!我现在正在使用以下代码:df["bucket"] = list(zip(pd.qcut(df["A"], 10, labels=list(range(10))), pd.qcut(df["B"], 10, labels=list(range(10))))),这是基于您的回答。 - AxelWass

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