I want to plot a true/false
or active/deactive
binary data similar to the following picture:
What you are looking for is imshow
:
import matplotlib.pyplot as plt
import numpy as np
# get some data with true @ probability 80 %
data = np.random.random((20, 500)) > .2
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data, aspect='auto', cmap=plt.cm.gray, interpolation='nearest')
Then you will just have to get the Y labels from somewhere.
It seems that the image in your question has some interpolation in the image. Let us set a few more things:
import matplotlib.pyplot as plt
import numpy as np
# create a bit more realistic-looking data
# - looks complicated, but just has a constant switch-off and switch-on probabilities
# per column
# - the result is a 20 x 500 array of booleans
p_switchon = 0.02
p_switchoff = 0.05
data = np.empty((20,500), dtype='bool')
data[:,0] = np.random.random(20) < .2
for c in range(1, 500):
r = np.random.random(20)
data[data[:,c-1],c] = (r > p_switchoff)[data[:,c-1]]
data[-data[:,c-1],c] = (r < p_switchon)[-data[:,c-1]]
# create some labels
labels = [ "label_{0:d}".format(i) for i in range(20) ]
# this is the real plotting part
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data, aspect='auto', cmap=plt.cm.gray)
ax.set_yticks(np.arange(len(labels)))
ax.set_yticklabels(labels)
creates
However, the interpolation is not necessarily a good thing here. To make the different rows easier to separate, one might use colors:
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
# create a bit more realistic-looking data
# - looks complicated, but just has a constant switch-off and switch-on probabilities
# per column
# - the result is a 20 x 500 array of booleans
p_switchon = 0.02
p_switchoff = 0.05
data = np.empty((20,500), dtype='bool')
data[:,0] = np.random.random(20) < .2
for c in range(1, 500):
r = np.random.random(20)
data[data[:,c-1],c] = (r > p_switchoff)[data[:,c-1]]
data[-data[:,c-1],c] = (r < p_switchon)[-data[:,c-1]]
# create some labels
labels = [ "label_{0:d}".format(i) for i in range(20) ]
# create a color map with random colors
colmap = matplotlib.colors.ListedColormap(np.random.random((21,3)))
colmap.colors[0] = [0,0,0]
# create some colorful data:
data_color = (1 + np.arange(data.shape[0]))[:, None] * data
# this is the real plotting part
fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data_color, aspect='auto', cmap=colmap, interpolation='nearest')
ax.set_yticks(np.arange(len(labels)))
ax.set_yticklabels(labels)
creates
Of course, you will want to use something less strange as the coloring scheme, but that is really up to your artistic views. Here the trick is that all True
elements on row n
have value n+1
and, and all False
elements are 0
in data_color
. This makes it possible to create a color map. Naturally, if you want a cyclic color map with two or three colors, just use the modulus of data_color
in imshow
by, e.g. data_color % 3
.