我正在用matplotlib绘制该图,for循环只是为背景着色:
fig, ax = plt.subplots()
ax.set_ylabel('Number of contacts')
ax.set_xlabel('Time [s]')
for m in range(len(data[node])):
if data[node][m] == -1:
ax.axvline(m,color='r',linewidth=5,alpha=0.2,label="OUT")
if data[node][m] == 0:
ax.axvline(m,color='g',linewidth=5,alpha=0.2,label="RZ0")
if data[node][m] == 1:
ax.axvline(m,color='y',linewidth=5,alpha=0.2,label="RZ1")
ax.plot(x, y, 'b+')
# ax.legend() # HERE is the problem
plt.show()
绘制以下内容:
我现在想要的是一个图例,以指示背景含义的每种颜色,但是当包含在内时ax.legend()
,出现以下错误:
ValueError: Image size of 392x648007 pixels is too large. It must be less than 2^16 in each
direction.
<Figure size 432x288 with 1 Axes>
<Figure size 432x288 with 0 Axes>
我应该如何命名背景的每种颜色,有43200条垂直线,但只有3种颜色,它与行数有关吗?
诀窍是仅将标签设置一次。您可以为每个标签添加一个变量,并在使用None
后将其替换为变量。注意,使用axvline
背景绘制存在以下问题:线宽是在像素空间中测量的,因此相邻的线会重叠或之间有小的空白。更好地使用axvspan
。为了避免左右两边的空白,您可以显式设置x限制。
使用循环可以稍微简化代码。
更新的代码:
from matplotlib import pyplot as plt
from matplotlib import colors as mcolors
import numpy as np
import pandas as pd
import itertools
fig, ax = plt.subplots()
# create some random data
x = np.arange(100)
y = np.sinh(x/20)
indicators = [-1, 0, 1]
node = 0
data = [np.random.choice(indicators, len(x), p=[10/16,1/16,5/16])]
labels = ["OUT", "RZ0", "RZ1"]
colors = ['lime', 'purple', 'gold']
alpha = 0.4
# precalculate the effect of alpha so the colors can be applied with alpha=1
colors = [[1 + (x - 1) * alpha for x in mcolors.to_rgb(c)] for c in colors]
m = 0
for val, group in itertools.groupby(data[node]):
width = len(list(group))
ind = indicators.index(val)
ax.axvspan(m, m + width, color=colors[ind], linewidth=0, alpha=1, label=labels[ind])
labels[ind] = None # reset the label to make sure it is only used once
m += width
ax.plot(x, y, 'b+')
ax.set_xlim(0, len(data[node]))
ax.legend(framealpha=1) # to make the legend background opaque
plt.show()
它有效,需要花费很长时间进行绘制,因为我的df很大,但是图像很棒。谢谢
可以更快地将相同颜色的后续跨度分组在一起。另外,您可以使用较柔和的颜色,而忽略Alpha。