Python – Plotting colored grid based on values
Question:
I have been searching here and on the net. I found somehow close questions/answers to what I want, but still couldn’t reach to what I’m looking for.
I have an array of for example, 100 values. The values are in the range from 0 to 100.
I want to plot this array as a grid, filling the squares according to the values in the array.
The solutions I found so far are like the followings:
Drawing grid pattern in matplotlib
and
custom matplotlib plot : chess board like table with colored cells
In the examples I mentioned, the ranges of the colors vary and are not fixed.
However, what I am wondering about, is whether I can set the ranges for specific values and colors.
For example,
if the values are between 10 and 20, let the color of the grid square be red.
else if the values are between 20 and 30, let the color be blue. etc.
How this could be achieved in python?
Answers:
You can create a ListedColormap for your custom colors and color BoundaryNorms to threshold the values.
import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
data = np.random.rand(10, 10) * 20
# create discrete colormap
cmap = colors.ListedColormap(['red', 'blue'])
bounds = [0,10,20]
norm = colors.BoundaryNorm(bounds, cmap.N)
fig, ax = plt.subplots()
ax.imshow(data, cmap=cmap, norm=norm)
# draw gridlines
ax.grid(which='major', axis='both', linestyle='-', color='k', linewidth=2)
ax.set_xticks(np.arange(-.5, 10, 1));
ax.set_yticks(np.arange(-.5, 10, 1));
plt.show()
For more, you can check this matplotlib example.
It depends on what units you need your colours to be in, but just a simple if statement should do the trick.
def find_colour(_val):
# Colour value constants
_colours = {"blue": [0.0, 0.0, 1.0],
"green": [0.0, 1.0, 0.00],
"yellow": [1.0, 1.0, 0.0],
"red": [1.0, 0.0, 0.0]}
# Map the value to a colour
_colour = [0, 0, 0]
if _val > 30:
_colour = _colours["red"]
elif _val > 20:
_colour = _colours["blue"]
elif _val > 10:
_colour = _colours["green"]
elif _val > 0:
_colour = _colours["yellow"]
return tuple(_colour)
And just convert that tuple to whatever units you need e.g. RGBA(..). You can then implement the methods it looks like you have already found to achieve the grid.
Based on @umotto’s answer a more sophisticated version:
import matplotlib as mlib
import matplotlib.pyplot as plt
import numpy as np
def plot_colored_grid(data, colors=['white', 'green'], bounds=[0, 0.5, 1], grid=True, labels=False, frame=True):
"""Plot 2d matrix with grid with well-defined colors for specific boundary values.
:param data: 2d matrix
:param colors: colors
:param bounds: bounds between which the respective color will be plotted
:param grid: whether grid should be plotted
:param labels: whether labels should be plotted
:param frame: whether frame should be plotted
"""
# create discrete colormap
cmap = mplt.colors.ListedColormap(colors)
norm = mplt.colors.BoundaryNorm(bounds, cmap.N)
# enable or disable frame
plt.figure(frameon=frame)
# show grid
if grid:
plt.grid(axis='both', color='k', linewidth=2)
plt.xticks(np.arange(0.5, data.shape[1], 1)) # correct grid sizes
plt.yticks(np.arange(0.5, data.shape[0], 1))
# disable labels
if not labels:
plt.tick_params(bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False)
# plot data matrix
plt.imshow(data, cmap=cmap, norm=norm)
# display main axis
plt.show()
If you want to plot for example a binary matrix plot_colored_grid(np.array([[True, False], [False, True]]))
will result in:
Another example:
data = np.array([
[9, 12, 24],
[5, 2, 33],
[27, 36, 15]
])
plot_colored_grid(data, colors=['white', 'green', 'purple', 'red'], bounds=[0, 10, 20, 30, 40])
This will result in:
I have been searching here and on the net. I found somehow close questions/answers to what I want, but still couldn’t reach to what I’m looking for.
I have an array of for example, 100 values. The values are in the range from 0 to 100.
I want to plot this array as a grid, filling the squares according to the values in the array.
The solutions I found so far are like the followings:
Drawing grid pattern in matplotlib
and
custom matplotlib plot : chess board like table with colored cells
In the examples I mentioned, the ranges of the colors vary and are not fixed.
However, what I am wondering about, is whether I can set the ranges for specific values and colors.
For example,
if the values are between 10 and 20, let the color of the grid square be red.
else if the values are between 20 and 30, let the color be blue. etc.
How this could be achieved in python?
You can create a ListedColormap for your custom colors and color BoundaryNorms to threshold the values.
import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
data = np.random.rand(10, 10) * 20
# create discrete colormap
cmap = colors.ListedColormap(['red', 'blue'])
bounds = [0,10,20]
norm = colors.BoundaryNorm(bounds, cmap.N)
fig, ax = plt.subplots()
ax.imshow(data, cmap=cmap, norm=norm)
# draw gridlines
ax.grid(which='major', axis='both', linestyle='-', color='k', linewidth=2)
ax.set_xticks(np.arange(-.5, 10, 1));
ax.set_yticks(np.arange(-.5, 10, 1));
plt.show()
For more, you can check this matplotlib example.
It depends on what units you need your colours to be in, but just a simple if statement should do the trick.
def find_colour(_val):
# Colour value constants
_colours = {"blue": [0.0, 0.0, 1.0],
"green": [0.0, 1.0, 0.00],
"yellow": [1.0, 1.0, 0.0],
"red": [1.0, 0.0, 0.0]}
# Map the value to a colour
_colour = [0, 0, 0]
if _val > 30:
_colour = _colours["red"]
elif _val > 20:
_colour = _colours["blue"]
elif _val > 10:
_colour = _colours["green"]
elif _val > 0:
_colour = _colours["yellow"]
return tuple(_colour)
And just convert that tuple to whatever units you need e.g. RGBA(..). You can then implement the methods it looks like you have already found to achieve the grid.
Based on @umotto’s answer a more sophisticated version:
import matplotlib as mlib
import matplotlib.pyplot as plt
import numpy as np
def plot_colored_grid(data, colors=['white', 'green'], bounds=[0, 0.5, 1], grid=True, labels=False, frame=True):
"""Plot 2d matrix with grid with well-defined colors for specific boundary values.
:param data: 2d matrix
:param colors: colors
:param bounds: bounds between which the respective color will be plotted
:param grid: whether grid should be plotted
:param labels: whether labels should be plotted
:param frame: whether frame should be plotted
"""
# create discrete colormap
cmap = mplt.colors.ListedColormap(colors)
norm = mplt.colors.BoundaryNorm(bounds, cmap.N)
# enable or disable frame
plt.figure(frameon=frame)
# show grid
if grid:
plt.grid(axis='both', color='k', linewidth=2)
plt.xticks(np.arange(0.5, data.shape[1], 1)) # correct grid sizes
plt.yticks(np.arange(0.5, data.shape[0], 1))
# disable labels
if not labels:
plt.tick_params(bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False)
# plot data matrix
plt.imshow(data, cmap=cmap, norm=norm)
# display main axis
plt.show()
If you want to plot for example a binary matrix plot_colored_grid(np.array([[True, False], [False, True]]))
will result in:
Another example:
data = np.array([
[9, 12, 24],
[5, 2, 33],
[27, 36, 15]
])
plot_colored_grid(data, colors=['white', 'green', 'purple', 'red'], bounds=[0, 10, 20, 30, 40])
This will result in: