Matplot:如何绘制真/假或激活/非激活数据?

16 投票
1 回答
22200 浏览
提问于 2025-04-18 18:20

我想画一个类似下面这个图片的图表,显示的是 true/falseactive/deactive 的二进制数据:

True/False Plot

横轴是时间,纵轴是一些实体(这里是一些传感器),它们的状态是激活(白色)或未激活(黑色)。我该如何使用 pyplot 来绘制这样的图表呢?

我搜索了一下,想找出这种图表的名称,但没有找到。

1 个回答

33

你需要的就是 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')

然后你只需要从某个地方获取 Y 轴的标签。

enter image description here

看起来你提问中的图片有一些插值处理。我们来设置几个额外的参数:

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)

这样可以生成

enter image description here

不过,这里的插值不一定是个好事。为了让不同的行更容易区分,可以使用颜色来帮助区分:

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)

这样可以生成

enter image description here

当然,你可能想用一些更好看的颜色方案,但这完全取决于你的审美。在这里的关键是,所有在第 n 行的 True 元素的值是 n+1,而所有的 False 元素在 data_color 中的值是 0。这样就可以创建一个颜色映射。如果你想要一个循环的颜色映射,包含两种或三种颜色,只需在 imshow 中对 data_color 取模,比如 data_color % 3

撰写回答