【问题标题】:Risk Matrix with PythyonPython 的风险矩阵
【发布时间】:2025-12-21 10:25:06
【问题描述】:

我正在尝试使用 Python 做一个整合严重性和概率的风险矩阵,我已经尝试过使用热图,它可能是迄今为止我找到的最接近的图表,但我认为它不代表基本结构的风险矩阵。下一张图片显示了我想要的矩阵图。我将不胜感激任何建议:图书馆、链接......任何能够绘制风险矩阵的图表。

这是我试图在风险矩阵中定位的数据:

|---------------------|------------------|----------------------|
|      Component      |        KPI       |     Classification             
|---------------------|------------------|----------------------|
|          12         |         34       |    High Criticality
|---------------------|------------------|----------------------|
          Start                 38            High Criticality
|---------------------|------------------|----------------------|
         Fusela                 45            Low Criticality
|---------------------|------------------|----------------------|
          Hyd                   50           Medium Criticality
|---------------------|------------------|----------------------|
          Damp                  51           Medium Criticality
|---------------------|------------------|----------------------|
         Turbine                62           High Criticality
|---------------------|------------------|----------------------|
        Intercon                65          Medium Criticality
|---------------------|------------------|----------------------|
       Main Rotor               90           High Criticality
|---------------------|------------------|----------------------|
         AM-19                  93            High Criticality
|---------------------|------------------|----------------------|
      Main Trans                98            High Criticality
|---------------------|------------------|----------------------|

这是我已经使用热图实现的代码:

import matplotlib.pyplot as plt

data = data.sort_values(by = 'KPI', ascending = False)
x = 1
for element in list(data['Componente']):
    data['Componente'] = data['Componente'].str.replace(str(element),'{}. 
{}'.format(str(x),element))
    x = x + 1
data['Clasificación'] = data['Clasificación'].str.replace('Criticidad 
Alta','1. Criticidad Alta').str.replace('Criticidad Media','2. Criticidad 
Media').str.replace('Criticidad Baja', '3. Criticidad Baja')
result = data.pivot(index='Componente',columns= 'Clasificacion', values = 
'KPI')
sb.heatmap(result, annot= True ,cmap='RdYlGn' ,fmt=".1f", vmax=100)
plt.figtext(.5,.9,'RESULTADO MATRIZ RIESGO', fontsize=14, ha='center')
plt.show()

我想要的输出类似于下一个成像器:

【问题讨论】:

  • 请发布您的代码和数据
  • @seralok 嗨,现在我加载数据和代码
  • @QuangHoang 完成!
  • 仍然不清楚您希望矩阵是什么样子?就您的数据而言,x 轴、y 轴、每个单元格上的内容是什么?
  • 你的哪一部分数据决定了可能性?

标签: python python-3.x matplotlib seaborn


【解决方案1】:

我有同样的需求并想出了下面的解决方案(利用来自Matplotlib Subplots -- Get Rid of Tick Labels Altogether 的想法/代码 sn-ps)。

绘图是使用无花果和多轴从头开始构建的,因此应该很容易根据需要进行修改/更新。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


fig = plt.figure()
plt.subplots_adjust(wspace=0, hspace=0)
plt.xticks([])
plt.yticks([])
plt.xlim(0, 5)
plt.ylim(0, 5)
plt.xlabel('Consequence')
plt.ylabel('Likelihood')
plt.title('Example of Risk Matrix Plot')

#This example is for a 5 * 5 matrix
nrows=5
ncols=5
axes = [fig.add_subplot(nrows, ncols, r * ncols + c + 1) for r in range(0, nrows) for c in range(0, ncols) ]

# remove the x and y ticks
for ax in axes:
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_xlim(0,5)
    ax.set_ylim(0,5)

#Add background colors
#This has been done manually for more fine-grained control
#Run the loop below to identify the indice of the axes

#Identify the index of the axes
#for i in range(len(axes)):
#    axes[i].text(0,0, i)

green = [10, 15, 16, 20 , 21] #Green boxes
yellow = [0, 5, 6, 11, 17, 22, 23] #yellow boxes
orange = [1 , 2, 7, 12, 13, 18, 19, 24] # orange boxes
red = [3, 4, 8, 9, 14] #red boxes

for _ in green:
    axes[_].set_facecolor('green')

for _ in yellow:
    axes[_].set_facecolor('yellow')

for _ in orange:
    axes[_].set_facecolor('orange')

for _ in red:
    axes[_].set_facecolor('red')


#Add labels to the Green boxes
axes[10].text(0.1,0.8, '4')
axes[15].text(0.1,0.8, '2')
axes[20].text(0.1,0.8, '1')
axes[16].text(0.1,0.8, '5')
axes[21].text(0.1,0.8, '3')


#Add labels to the Yellow boxes
axes[0].text(0.1,0.8, '11')
axes[5].text(0.1,0.8, '7')
axes[6].text(0.1,0.8, '12')
axes[11].text(0.1,0.8, '8')
axes[17].text(0.1,0.8, '9')
axes[22].text(0.1,0.8, '6')
axes[23].text(0.1,0.8, '10')

#Add lables to the Orange boxes
axes[1].text(0.1,0.8, '16')
axes[2].text(0.1,0.8, '20')
axes[7].text(0.1,0.8, '17')
axes[12].text(0.1,0.8, '13')
axes[13].text(0.1,0.8, '18')
axes[18].text(0.1,0.8, '14')
axes[19].text(0.1,0.8, '19')
axes[24].text(0.1,0.8, '15')

#Add lables to the Red Boxes
axes[3].text(0.1,0.8, '23')
axes[8].text(0.1,0.8, '21')
axes[4].text(0.1,0.8, '25')
axes[9].text(0.1,0.8, '24')
axes[14].text(0.1,0.8, '22')

#Plot some data

for _ in range(len(axes)):
        axes[_].plot(np.random.uniform(2, 4, 5), np.random.uniform(2,4,5), '.')
plt.show()

【讨论】:

    【解决方案2】:

    这是一个关于 plt.imshow 和 plt.annotate 的想法:

    # function to make risk matrix
    def make_risk_matrix(shape=3,levels=3):
        matrix = np.zeros((shape, shape))
        for level in range(levels):
            matrix[np.triu_indices(shape, level)] += 1
        return matrix
    
    # specify bin borders and respective positions
    likelihood_bins = [100,86,60]
    positions = [0,1,2]
    
    for position, likelihood in zip(positions, likelihood_bins):
        df.loc[df['KPI']<=likelihood, 'y'] = position
    
    # generate x-positions from classification column
    df['x'] = df['Classification'].replace({'High':2, 'Medium':1, 'Low':0})
    
    # default offset for x -position
    x_offset = -.4
    
    # generate risk matrix and display as image
    risk_matrix = make_risk_matrix()
    plt.imshow(risk_matrix, cmap='RdYlGn_r')
    
    # write individual components on it
    # as some components will end up in hte same bin,
    # caculate y-offset on the fly
    for group in df.groupby(['x', 'y']):
        y_offset = -.3
        for ix, row in group[1].iterrows():
    
            plt.annotate(
                row['Component'], 
                xy=(
                    row['x']+x_offset,
                    row['y']+y_offset
                    )
                )
            y_offset +=.15 # update y_offset
    
    plt.xlabel('Consequence')
    plt.ylabel('Likelihood')
    

    我使用的df是这个:

        Component   KPI Classification
    1   12          34  High
    2   Start       38  High
    3   Fusela      45  Low
    4   Hyd         50  Medium
    [...]
    

    【讨论】:

    • 这正是我需要的,我只需要更改轴的名称,你知道是否可以吗?
    • 感谢您的时间和代码,这正是我所需要的