用于 seaborn 热图的二维数组中的 Bin DataFrame

Bin DataFrame in 2D array for seaborn heatmap

我有一个看起来像的数据框。

+-----------+-------+
|     A     |   B   |
+-----------+-------+
|     1     |   1   |
|     2     |   2   |
|     5     |   3   |
|    20     |   4   |
|    25     |   3   |
|    123    |   5   |
|    125    |   6   |
+-----------+-------+

我想根据定义的范围与列 B 中值的总和对列 A 进行分箱。然后将其提供给 seaborn 以生成热图。

+---------+------+-------+-------+-------+-------+-------+-------+-------+-------+--------+
|         | 0-10 | 11-20 | 21-30 | 31-40 | 41-50 | 51-60 | 61-70 | 71-80 | 81-90 | 91-100 |
+---------+------+-------+-------+-------+-------+-------+-------+-------+-------+--------+
|  0-100  |  6   |   4   |   3   |   0   |   0   |   0   |   0   |   0   |   0   |   0    |
| 101-200 |  0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0    |
| 201-300 |  0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0    |
| 301-400 |  0   |   0   |  11   |   0   |   0   |   0   |   0   |   0   |   0   |   0    |
| 401-500 |  0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0   |   0    |
+---------+------+-------+-------+-------+-------+-------+-------+-------+-------+--------+

一种解决方法是循环遍历数据并生成数组。如果有的话,我正在寻找pandas方式。

我尝试使用 seaborn.heatmap 解决问题,如下所示:

df.groupby([pd.cut(df.A, bins=[x for x in range(0,1001,100)], include_lowest=True, right=False),
            pd.cut(df.A, bins=[x for x in range(0,101,10)], include_lowest=True, right=False)])
           .B.sum().unstack()

但这仅是按前 0-100 B 值分组的。忽略剩余的。

在您的解决方案中,range(0,101,10) 使用最大 range,例如 101,因此 A 列中的不匹配值大于 100 - 输出是NaNs,所以合计后得到0.

编辑:

#create helper column with integer and modulo division
df['A1'] = df.A % 100

bins1= range(0,df.A.max() // 100 * 100 + 101, 100)
bins2= range(0,df.A1.max() // 10 * 10 + 11, 10)

labels1 = [f'{i}-{j}' if i == 0 else f'{i + 1}-{j}' for i, j in zip(bins1[:-1], bins1[1:])] 
labels2 = [f'{i}-{j}' if i == 0 else f'{i + 1}-{j}' for i, j in zip(bins2[:-1], bins2[1:])] 


df['a'] = pd.cut(df.A, bins=bins1,labels=labels1, include_lowest=True, right=True)
df['b'] = pd.cut(df.A1, bins=bins2,labels=labels2, include_lowest=True, right=True)
print (df)
     A  B  A1        a      b
0    1  1   1    0-100   0-10
1    2  2   2    0-100   0-10
2    5  3   5    0-100   0-10
3   20  4  20    0-100  11-20
4   25  3  25    0-100  21-30
5  123  5  23  101-200  21-30
6  125  6  25  101-200  21-30

df1 = df.pivot_table(index='a', columns='b', values='B', aggfunc='sum')
print (df1)
b        0-10  11-20  21-30
a                          
0-100       6      4      3
101-200     0      0     11