Bqplot 在动画的每一步渲染新条而不是移动原始条
Bqplot rendering new bar at each step in animation instead of moving the original bar
我正在尝试在 Bqplot 中制作条形图的动画。我希望能够同时更新条形的 x 和 y 值并让它们平滑调整。
下面的代码对于我图表中 3 个条形图中的 2 个条形图的行为符合预期,但第 3 个条形图在每个时间步完全重绘。
我最初只尝试了 2 个小节。第一个条的行为符合预期,但第二个条将在每个时间步重新绘制。我添加了第 3 个栏以尝试解决问题。
initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
with bar3.hold_sync():
bar3.x = [idxSlider3.value,
idxSlider3.value + 1,
idxSlider3.value + 2]
bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value]
idxSlider3.observe(update_chart3, 'value')
fig3 = plt.figure(animation_duration=1000)
bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])
play_button3 = Play(min=0, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])
当你说 'adjust' 流畅时,你想让条形图向右移动,而不重绘?我认为 bqplot 'moves' 不是那样的。新柱 1 和 2 的数据已经存在(因为它们被绘制为旧柱 2 和 3),所以它们不会重绘。新的 bar 3 数据以前是不存在的,这需要从头开始绘制。这给出了周围 'moving' 条的外观。
举一个不同的例子,观察当您将条形移动一个单位时会发生什么,但它们之间的间距为 两个 个单位。您应该每次都看到所有条形图都是从头开始绘制的。
from ipywidgets import *
import bqplot.pyplot as plt
initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
with bar3.hold_sync():
bar3.x = [idxSlider3.value,
idxSlider3.value + 2,
idxSlider3.value + 4]
bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value]
idxSlider3.observe(update_chart3, 'value')
fig3 = plt.figure(animation_duration=1000)
bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])
play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])
这是使 'bars' 在 x 中很好地动画化的方法。它不能用酒吧来完成。相反,我使用了线标记——这是一种技巧。但是您可以获得灵活性。而且我更喜欢在对象模型中使用 Bqplot(而不是 pyplot 方式)。
import bqplot as bq
from ipywidgets import *
import numpy as np
initialIndex = 0
xBar=[0, 2, 4]
yBar=[1, 1, 0]
zeroY = 0
barWidth = 1
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
xBar = [idxSlider3.value,
idxSlider3.value + 2,
idxSlider3.value + 4]
np.random.rand()
yBar = [idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2]
xList, yList = getLineCoordsFromBarLike(xBar, yBar)
lines.x = xList
lines.y = yList
idxSlider3.observe(update_chart3, 'value')
x_sc = bq.LinearScale()
y_sc = bq.LinearScale()
x_ax1 = bq.Axis(label='', scale=x_sc, num_ticks = 3)
y_ax1 = bq.Axis(label='', scale=y_sc, orientation='vertical')
def getLineCoordsFromBarLike(xBar, yBar):
""" Convert of single list of bar coordinates to a 2D array of line coordinates that describe the rectangular shape
xBar: 1D list of numbers for central x position of bar chart
yBar: 1D list of numbers for amplitudes of bar chart (must be same length as xBar)
retrns x cordinates 2D array, y coordinates 2D array.
"""
xList= []
yList= []
for num, x in enumerate(xBar):
y = yBar[num]
xList.append([x - barWidth/2, x - barWidth/2, x + barWidth/2, x + barWidth/2,])
yList.append([zeroY, y, y, zeroY])
x_ax1.tick_values = xBar
return xList, yList
xList, yList = getLineCoordsFromBarLike(xBar, yBar)
lines = bq.Lines(x=xList, y=yList,
scales={'x': x_sc, 'y': y_sc},
colors=['black'],
display_legend=True,
# tooltip=def_tt,
stroke_width = .5,
close_path = True,
fill = 'inside',
fill_colors = bq.colorschemes.CATEGORY10 * 10
)
margins = dict(top=10, bottom=40, left=50, right=30)
fig3 = bq.Figure(marks=[lines], axes=[x_ax1, y_ax1], fig_margin=margins, animation_duration=1000)
fig3.layout.width = '600px'
fig3.layout.height = '600px'
# def_tt = bq.Tooltip(fields=['name',], formats=['',], labels=['id', ])
play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])
我正在尝试在 Bqplot 中制作条形图的动画。我希望能够同时更新条形的 x 和 y 值并让它们平滑调整。 下面的代码对于我图表中 3 个条形图中的 2 个条形图的行为符合预期,但第 3 个条形图在每个时间步完全重绘。
我最初只尝试了 2 个小节。第一个条的行为符合预期,但第二个条将在每个时间步重新绘制。我添加了第 3 个栏以尝试解决问题。
initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
with bar3.hold_sync():
bar3.x = [idxSlider3.value,
idxSlider3.value + 1,
idxSlider3.value + 2]
bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value]
idxSlider3.observe(update_chart3, 'value')
fig3 = plt.figure(animation_duration=1000)
bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])
play_button3 = Play(min=0, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])
当你说 'adjust' 流畅时,你想让条形图向右移动,而不重绘?我认为 bqplot 'moves' 不是那样的。新柱 1 和 2 的数据已经存在(因为它们被绘制为旧柱 2 和 3),所以它们不会重绘。新的 bar 3 数据以前是不存在的,这需要从头开始绘制。这给出了周围 'moving' 条的外观。
举一个不同的例子,观察当您将条形移动一个单位时会发生什么,但它们之间的间距为 两个 个单位。您应该每次都看到所有条形图都是从头开始绘制的。
from ipywidgets import *
import bqplot.pyplot as plt
initialIndex = 0
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
with bar3.hold_sync():
bar3.x = [idxSlider3.value,
idxSlider3.value + 2,
idxSlider3.value + 4]
bar3.y = [idxSlider3.value, idxSlider3.value, idxSlider3.value]
idxSlider3.observe(update_chart3, 'value')
fig3 = plt.figure(animation_duration=1000)
bar3 = plt.bar(x=[0, 1, 2], y=[1, 1, 0])
play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])
这是使 'bars' 在 x 中很好地动画化的方法。它不能用酒吧来完成。相反,我使用了线标记——这是一种技巧。但是您可以获得灵活性。而且我更喜欢在对象模型中使用 Bqplot(而不是 pyplot 方式)。
import bqplot as bq
from ipywidgets import *
import numpy as np
initialIndex = 0
xBar=[0, 2, 4]
yBar=[1, 1, 0]
zeroY = 0
barWidth = 1
idxSlider3 = IntSlider(min=0, max=20, step=1,
description='Index',value=initialIndex)
''' I want to update the bar chart with this function '''
def update_chart3(change):
xBar = [idxSlider3.value,
idxSlider3.value + 2,
idxSlider3.value + 4]
np.random.rand()
yBar = [idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2, idxSlider3.value + np.random.rand()*2]
xList, yList = getLineCoordsFromBarLike(xBar, yBar)
lines.x = xList
lines.y = yList
idxSlider3.observe(update_chart3, 'value')
x_sc = bq.LinearScale()
y_sc = bq.LinearScale()
x_ax1 = bq.Axis(label='', scale=x_sc, num_ticks = 3)
y_ax1 = bq.Axis(label='', scale=y_sc, orientation='vertical')
def getLineCoordsFromBarLike(xBar, yBar):
""" Convert of single list of bar coordinates to a 2D array of line coordinates that describe the rectangular shape
xBar: 1D list of numbers for central x position of bar chart
yBar: 1D list of numbers for amplitudes of bar chart (must be same length as xBar)
retrns x cordinates 2D array, y coordinates 2D array.
"""
xList= []
yList= []
for num, x in enumerate(xBar):
y = yBar[num]
xList.append([x - barWidth/2, x - barWidth/2, x + barWidth/2, x + barWidth/2,])
yList.append([zeroY, y, y, zeroY])
x_ax1.tick_values = xBar
return xList, yList
xList, yList = getLineCoordsFromBarLike(xBar, yBar)
lines = bq.Lines(x=xList, y=yList,
scales={'x': x_sc, 'y': y_sc},
colors=['black'],
display_legend=True,
# tooltip=def_tt,
stroke_width = .5,
close_path = True,
fill = 'inside',
fill_colors = bq.colorschemes.CATEGORY10 * 10
)
margins = dict(top=10, bottom=40, left=50, right=30)
fig3 = bq.Figure(marks=[lines], axes=[x_ax1, y_ax1], fig_margin=margins, animation_duration=1000)
fig3.layout.width = '600px'
fig3.layout.height = '600px'
# def_tt = bq.Tooltip(fields=['name',], formats=['',], labels=['id', ])
play_button3 = Play(min=1, max=20, step=1, interval=1000, initial_value=0)
jslink((play_button3, 'value'), (idxSlider3, 'value'))
VBox([HBox([idxSlider3, play_button3]), fig3])