我正在创建一些数据的小提琴图,然后我将一个散点图与单个数据点(例如红点)渲染到三个子图。
由于小提琴图的生成相对耗时,我只生成一次小提琴图,然后为一个数据行添加散点图,写入结果文件,从轴中删除散点图并添加散点图下一行。
一切正常,但我想在保存之前添加选项,以显示()每个图。
如果我使用plt.show()
,图形会正确显示,但之后图像似乎被清除,在下一次迭代中,我没有小提琴图。
有没有办法在plt.show()之后保留图的内容?
简而言之,我的代码是
fig = generate_plot(ws, show=False) #returns the fig instance of the violin plot
#if I do plt.show() here (or in "generate_plot()"), the violin plots are gone.
ax1, ax3, ax2 = fig.get_axes()
scatter1 = ax1.scatter(...) #draw scatter plot for first axes
[...] #same vor every axis
plt.savefig(...)
scatter1.remove()
答案 0 :(得分:2)
我在想可能的选择是使用事件循环来推进这些图。以下将定义更新功能,该功能仅更改散点,绘制图像并保存。我们可以通过一个带有key_press回调的类来管理它 - 这样当你点击 Space 时,会显示下一个图像;在最后一张图像上按 Space 时,图表将被关闭。
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
class NextPlotter(object):
def __init__(self, fig, func, n):
self.__dict__.update(locals())
self.i = 0
self.cid = self.fig.canvas.mpl_connect("key_press_event", self.adv)
def adv(self, evt):
if evt.key == " " and self.i < self.n:
self.func(self.i)
self.i+=1
elif self.i >= self.n:
plt.close("all")
#Start of code:
# Create data
pos = [1, 2, 4, 5, 7, 8]
data = [np.random.normal(0, std, size=100) for std in pos]
data2 = [np.random.rayleigh(std, size=100) for std in pos]
scatterdata = np.random.normal(0, 5, size=(10,len(pos)))
#Create plot
fig, axes = plt.subplots(ncols=2)
axes[0].violinplot(data, pos, points=40, widths=0.9,
showmeans=True, showextrema=True, showmedians=True)
axes[1].violinplot(data2, pos, points=40, widths=0.9,
showmeans=True, showextrema=True, showmedians=True)
scatter = axes[0].scatter(pos, scatterdata[0,:], c="crimson", s=60)
scatter2 = axes[1].scatter(pos, scatterdata[1,:], c="crimson", s=60)
# define updating function
def update(i):
scatter.set_offsets(np.c_[pos,scatterdata[2*i,:]])
scatter2.set_offsets(np.c_[pos,scatterdata[2*i+1,:]])
fig.canvas.draw()
plt.savefig("plot{i}.png".format(i=i))
# instantiate NextPlotter; press <space> to advance to the next image
c = NextPlotter(fig, update, len(scatterdata)//2)
plt.show()
答案 1 :(得分:0)
解决方法可能是不删除散点图。
为什么不保留散点图轴,只更新该组轴的数据?
更新散点图数据后,您很可能需要plt.draw()
才能强制进行新的渲染。
答案 2 :(得分:0)
我找到了一种以交互方式绘制数字的方法here。 plt.ion()
阻止input()
进程似乎很重要。
import matplotlib.pyplot as plt
plt.ion()
fig = plt.figure()
ax = plt.subplot(1,1,1)
ax.set_xlim([-1, 5])
ax.set_ylim([-1, 5])
ax.grid('on')
for i in range(5):
lineObject = ax.plot(i,i,'ro')
fig.savefig('%02d.png'%i)
# plt.draw() # not necessary?
input()
lineObject[0].remove()
我还尝试使用time.sleep(1)
阻止该过程,但它根本不起作用。