Home > Back-end >  How can I make a problem matrix with percentage using matplotlib and seaborn?
How can I make a problem matrix with percentage using matplotlib and seaborn?

Time:04-01

I want to make this type of graph you see below. I get that I can make a matrix graph with matplotlib like so

    cmap = colors.ListedColormap(['white','red'])
data = [
    [0,0,0,0,0,1,1,1,1,],
    [0,0,0,0,0,1,0,0,1,],
]
plt.figure(figsize=(9,5))
plt.pcolor(data[::-1],cmap=cmap,edgecolors='k', linewidths=3)
plt.xlabel('Problem') 
plt.ylabel('Particpant')
plt.show()

But how would I go about adding percentages to be included in this graph?

I want to make this type of graph

CodePudding user response:

You can add a secondary x-axis (ax.twiny()), using the top axis for the numbering and the bottom axis to show the percentages.

Calling pcolor with a list of x and y positions that are 0.5 shifted will put the ticks and tick labels at integer positions. clip_on=False makes sure the outer cell borders have the same thickness as the rest. ax.invert_yaxis() lets you invert the y axis (so you can use data instead of data[::-1]).

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np

cmap = ListedColormap(['white', 'orangered'])
data = np.random.randint(0, 3, size=(28, 30)) % 2
data[:, 9] = 1  # one full column to simulate 100%
data[:, 11] = 0  # one empty  column to simulate 0%
fig, ax = plt.subplots(figsize=(9, 5))
ax.pcolor(np.arange(data.shape[1]   1)   0.5, np.arange(data.shape[0]   1)   0.5, data,
          cmap=cmap, edgecolors='k', linewidths=3, clip_on=False)
ax.set_yticks(range(1, data.shape[0]   1))
ax.set_xticks(range(1, data.shape[1]   1))
ax.set_xticklabels([f'{p:.0f}' for p in data.mean(axis=0) * 100])
ax.invert_yaxis()

ax2 = ax.twiny()
ax2.set_xlim(ax.get_xlim())
ax2.set_xticks(range(1, data.shape[1]   1))
ax2.set_xlabel('Problem')
ax.tick_params(length=0)
ax2.tick_params(length=0)
ax.set_ylabel('Particpant')
plt.tight_layout()
plt.show()

pcolor with shifted cell borders, secondary ax for extra info

Decreasing the fontsize (or increasing the figsize) allows to also show the percentage sign:

ax.set_xticklabels([f'{p:.0f}%' for p in data.mean(axis=0) * 100], fontsize=8)
  • Related