Pandas,绘制热图和矩阵

Pandas, plotly heatmaps and matrix

我正在使用 python 3.8,plotly 4.14.1,pandas1.2.0

我不知道如何在 pandas 中分离数据并将数据分配给计数器以便更新热图。

我想创建一个影响 x 可能性的风险矩阵,并将这些数字显示在 Plotly 热图上。

将数据硬编码到数据帧中,它按预期工作

下图工厂

gross_data=[[0,1,2,6,3], [0,7,18,12,6], [6,10,43,44,7], [3,15,29,46,18], [5,14,26,22,21]]

x=['Minor [Very Low]<br>1', 'Important [Low]<br>2', 'Significant [Moderate]<br>3', 'Major [High]<br>4', 'Critical [Very High]<br>5']
y=['Very Remote<br>1', 'Remote<br>2', 'Unlikely<br>3', 'Possible<br>4', 'Highly Possible<br>5']

fig = ff.create_annotated_heatmap(gross_data, x=x, y=y, colorscale='Magma')
fig['layout']['xaxis']['side'] = 'bottom'
fig.show()

Plotly Figfure Factory 注释热图

或使用 plotly express

gross_data=[[0,1,2,6,3], [0,7,18,12,6], [6,10,43,44,7], [3,15,29,46,18], [5,14,26,22,21]]

fig = px.imshow(gross_data,
                labels=dict(x="Impact", y="Probability", color="Number of Risks"),
                x=['Minor [Very Low]', 'Important [Low]', 'Significant [Moderate]', 'Major [High]', 'Critical [Very High]'],
                y=['Very Remote', 'Remote', 'Unlikely', 'Possible', 'Highly Possible']
               )
fig.update_xaxes(side="bottom")

fig.show()

绘制热图

现在,这些都可以用于一次性演示,但我希望能够对我的数据进行切片和切块,并按业务部门等显示。

我正在使用 pandas 读取大约 1000 行 excel 数据,这些数据已由人工填写为表格,其中包含所有带来的错误。我整理了一下,清理了数据。

我无法解决的是如何获取为风险矩阵中的每个单元格提供大小所需的数据,而无需像下面这样的大量 if 语句。

for X in df[gross_impact]:
    for y in df[gross_likelihood]:
        if (x == 1) & (y == 1):
            increment a counter associated with cell x1y1
       elif (x == 2) & (y == 1):
            increment a counter associated with cell x2y1
       elif (x == 3) & (y == 1):
            increment a counter associated with cell x3y1
       elif (x == 4) & (y == 1):
            increment a counter associated with cell x4y1
       elif (x == 4) & (y == 1):
            increment a counter associated with cell x5y1
       elif (x == 1) & (y == 2):
            increment a counter associated with cell x1y2
       elif (x == 2) & (y == 2):
            increment a counter associated with cell x2y2
      .....
      .....
      elif (x == 5) & (y == 5):
        increment a counter associated with cell x5y5

这显然是完全低效的。 id 运行 通过大约 233,000 次循环得到我的结果,虽然计算资源很便宜,但这并不正确。

我只是想不通我应该怎么做。我已经阅读了几个堆栈交换问题,但它们没有解决我的查询。我在网上进行了研究以寻找风险矩阵,但结果以 C++ 或财务数据的形式返回,看起来并不适用。

我的数据框有大约 30 个字段,但唯一参考是 risk_id。我正在相互乘法的字段是 risk_impact 和 risk_likelihood。我可以对 risk_id 和 business_unit

进行排序

我必须区分 1 x 3 和 3 x 1,因为它们会进入两个不同的箱子 计数应从左下角到右上角,因此 1 x 3 是第 1 列第 3 行。3 x 1 是第 3 列第 1 行

希望这很清楚。如果我确切地知道该要求什么,我可能已经做到了

如能提供解决此问题的任何帮助,我们将不胜感激。

这是我的 datafrae 中的数据示例

import pandas as pf

# Our data to be loaded into the data frame
data = {'risk_id': ['AP-P01-R01', 'AP-P02-R02', 'AP-P03-R03', 'AP-P01-R04', 'BP-P01-R01', 'BP-P01-R02', 'BP-P01-R03', 'BP-P01-R04', 'BP-P01-R05', 'BP-P01-R06', 'BP-P01-R07', 'CP-P01-R01', 'CP-P01-R02', 'CP-P01-R03', 'CP-P01-R04', 'CP-P01-R05', 'CP-P01-R06', 'CP-P01-R07', 'CP-P01-R08'],
        'gross_impact': [4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4, 2, 3, 5, 3, 2],
        'gross_likelihood': [3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 2, 3, 3, 3, 3, 4, 4, 5, 3],
        'business_unit': ['Accounts Payable', 'Accounts Payable', 'Accounts Payable', 'Accounts Payable', 'British Petroleum', 'British Petroleum', 'British Petroleum', 'British Petroleum', 'British Petroleum', 'British Petroleum', 'British Petroleum', 'Client Profile', 'Client Profile', 'Client Profile', 'Client Profile', 'Client Profile', 'Client Profile', 'Client Profile', 'Client Profile']
        }

这一切都很好

使用提供的解决方案在我有限的数据集上运行得很好。 当我使用我的主文件创建一个 pandas 数据框时,出现以下错误

IndexError: arrays used as indices must be of integer (or boolean) type

当我 运行 代码及其下面抛出 错误

heatmap[counts[:,1]-1, counts[:,0]-1] = counts[:,2]

完整代码我运行ning是

df = raca_df[['risk_id', 'gross_impact','gross_likelihood', 'business_unit']].dropna()
counts = df.groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values

heatmap = np.zeros((np.max(5), np.max(5)))
#heatmap = np.zeros((np.max(df['gross_impact']), np.max(df['gross_likelihood'])))
heatmap[counts[:,1]-1, counts[:,0]-1] = counts[:,2]

import plotly.figure_factory as ff
fig = ff.create_annotated_heatmap(heatmap)
fig['layout']['xaxis']['side'] = 'bottom'
fig.show()

在提示我如何创建 raca df 后,raca_df.info 快速指出了我的问题。结果证明这是我原来的 raca_df 数据框和列类型为 float64 的问题。我在该列中也有一些空白条目,所以它不允许我更改那里的列类型。

我不得不从 raca_df 想象中创建一个新的数据框,称为 df 并且我使用循环和 astype('int')

更改了那里的列类型
df = raca_df[['risk_id', 'gross_impact','gross_likelihood', 'business_unit']].dropna()

for item in ['gross_impact','gross_likelihood', 'net_impact', 'net_likelihood']:
    raca_df[item] = raca_df[item].astype('int')

您可以按影响和可能性分组并使用分组大小来获取热图强度:

counts = df.groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values

# then, you can initialise an empty heatmap and use fancy indexing to populate it:    
heatmap = np.zeros((np.max(df['gross_impact']), np.max(df['gross_likelihood'])))
heatmap[counts[:,0]-1, counts[:,1]-1] = counts[:,2]

# and finally plot it
import plotly.figure_factory as ff
fig = ff.create_annotated_heatmap(heatmap)
fig.show()

编辑:

对于各个业务部门,您可以 运行 相同的代码,并进行以下任一调整:

# for a single business unit
counts = df[df['business_unit']=='Accounts Payable'].groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values

# and then the remaining code


# for all units, you can loop:
for business_unit in set(df['business unit']):
    counts = df[df['business unit']==business_unit].groupby(['gross_impact','gross_likelihood']).apply(len).reset_index().values
    
    # and then the remaining code