python - 重新绘制 2 个 pyplot 图表而不重新绘制新图表
问题描述
编辑:添加了导入语句以使代码示例完全独立。
我正在尝试更新已经在原地绘制的 pyplot 图表,而不绘制新图表。我在这个主题上找到了这个帖子,我想我遵循了它包含的所有建议,但我仍然无法让它发挥作用。该线程是关于更新一个单一的数字。我试图在两个数字之间来回切换,我认为这就是导致问题的原因。感觉好像用 plt.figure() 以某种方式切换回已经激活的图形正在创建一个新图形,而不是重新激活现有图形。
这是我的代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import ipywidgets as widgets
import time
def display_charts( data1, data2, fig1, fig2 ):
# Plot charts
#plt.figure(fig1.number) # Intended to make EXISTING figure current, without creating new one
fig1.clf() # I was hoping this would clear the figure allowing it to be re-drawn in-price, but
# it doesn't seem to help
ax=fig1.gca() # Get axes for this figure
ax.clear() # Tried this based on Stack Overflow thread, but doesn't seem to help
data1.plot.line(ax=ax)
fig1.canvas.draw() # Got these two lines from a stack overflow discussion about redrawing
fig1.canvas.flush_events() # charts in-place but they don't seem to help.
#plt.figure(fig2.number)
fig2.clf()
ax2 = fig2.gca()
ax2.clear()
data2.plot.bar(ax=ax2)
fig2.canvas.draw()
fig2.canvas.flush_events()
def update_button_callback(_):
# My hope was that this would allow the charts to be re-drawn in place with new data. But that
# doesn't work. Instead, when the button is clicked, 2 new smaller charts are drawn under the
# original ones.
display_charts( df3, df4, fig1, fig2 ) # I want this to update the charts in place, not draw them a 2nd time!!!
# Set up sample data for illustration
df1 = pd.DataFrame([1.2,3.4,5.6,7.8,9.0],[3.4,5.6,7.8,9.0,1.2])
df2 = pd.DataFrame([11.2,13.4,15.16,17.18,19.0],[13.14,15.16,17.8,19.0,11.2])
df3 = pd.DataFrame([21.2,23.4,25.6,27.8,29.0],[23.4,25.6,27.8,29.0,21.2])
df4 = pd.DataFrame([31.2,33.4,35.6,37.8,39.0],[33.4,35.6,37.8,39.0,31.2])
# Configure and display UI controls
plt.ion() # I don't think this should be required, but threw it in just in case...
fig1=plt.figure(figsize=(30,20)) # These figure sizes get used the FIRST time the charts are drawn, but
fig2=plt.figure(figsize=(30,20)) # when I try and update in place, the result is to draw new charts which
# default to a smaller display size.
update_button = widgets.Button(description="Update Chart")
display(update_button)
update_button.on_click(update_button_callback)
display_charts(df1,df2, fig1, fig2) # Display first 2 df's. Button click callback will update them.
plt.show()
time.sleep(5) # Isolate out any issues with the button control being the problem by waiting 5 seconds
# then calling display_charts() a 2nd time with the other df's.
print("Updating charts now...")
display_charts(df3,df4, fig1, fig2) # Display first 2 df's. Button click callback will update them.
plt.show()
time.sleep(10)
print("exiting cell")
我意识到在 fig.clf() 之后对 ax.clear() 的调用是多余的。我只是试图覆盖所有可能的基础。此外,我尝试了几乎所有可能的组合,即省略或包括每个 clear、clf、draw 和 flush 操作。我所做的一切似乎都不起作用。
奇怪的是,在 display_charts() 函数第一次运行时使用了主代码(底部)中设置的图形大小。但是所有后续执行都会导致新图表以小得多的默认图形大小显示。这使我得出结论,正在创建新数据而不是更新旧数据,但我不知道为什么。
提前感谢您的任何见解!
ps 我在一个图中使用两个单独的图而不是 2 个子图的原因是在实际代码中(为了清楚起见,这篇文章包含了一个简化),有完全不同的 xticks 和 yticks 设置以及一堆其他图设置不同。还有 3 个而不是 2 个图表。真正的代码被精简为重现问题的最简单版本,如上所示。
解决方案
这是一个选项,在按下按钮时清除输出。
#Cell 1
%matplotlib inline
#Cell 2
import matplotlib.pyplot as plt
import pandas as pd
import ipywidgets as widgets
from IPython.display import display, clear_output
import time
#Cell 3
def display_charts(data1, data2):
ax1.clear()
data1.plot.line(ax=ax1)
ax2.clear()
data2.plot.line(ax=ax2)
df1 = pd.DataFrame([1.2,3.4,5.6,7.8,9.0],[3.4,5.6,7.8,9.0,1.2])
df2 = pd.DataFrame([11.2,13.4,15.16,17.18,19.0],[13.14,15.16,17.8,19.0,11.2])
df3 = pd.DataFrame([21.2,23.4,25.6,27.8,29.0],[23.4,25.6,27.8,29.0,21.2])
df4 = pd.DataFrame([31.2,33.4,35.6,37.8,39.0],[33.4,35.6,37.8,39.0,31.2])
fig1, ax1 = plt.subplots(figsize=(8,6))
fig2, ax2 = plt.subplots(figsize=(8,6))
def update_button_callback(evt):
clear_output(True)
display(update_button)
display_charts(df3, df4)
display(fig1)
display(fig2)
update_button = widgets.Button(description="Update Chart")
update_button.on_click(update_button_callback)
display(update_button)
display_charts(df1,df2)
推荐阅读
- ffmpeg - 如何使用 ffmpeg 解密加密的 mp4 文件
- java - Jacoco 如何正确排除包
- octave - 绘制两个相同的功能,但看起来不同
- sql - 如果月份更改,则在 sql 查询之间不起作用
- speech-to-text - 缺少 getUserMedia MediaRecorder 数据
- php - 如何在将 google+ 登录与我们的网站集成时解决错误 400(OAuth_error)?
- sony - Sony Remote API with a7 iii getAvailableFNumber 40404
- hibernate - 我该如何解决这个 Spring UnsatisfiedDependencyException
- azure - Service Fabric:图像下载过程中出错
- google-cloud-storage - 是否可以通过 Google Cloud Storage 在 Google Compute Instance 中提供静态文件?