I want to build a histogram for the normal distribution and update the plot when the mean, standard deviation and sample size are changed; analogue to the post here.
However, I struggle with the update
function. In the example above
l, = plot(f(S, 1.0, 1.0))
and
def update(val):
l.set_ydata(f(S, sGmax.val, sKm.val))
are used but how would this have to be changed when a histogram is plotted? So, I am not sure how to use the return values from plt.hist
, pass them properly to update
and then update the plot accordingly. Could anyone explain this?
This is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def update(val):
mv = smean.val
stdv = sstd.val
n_sample = round(sn.val)
# what needs to go here? how to replace xxx
xxx(np.random.normal(mv, stdv, n_sample))
plt.draw()
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
m0 = -2.5
std0 = 1
n0 = 1000
n_bins0 = 20
nd = np.random.normal(m0, std0, n0)
# what needs to be returned here?
plt.hist(nd, normed=True, bins=n_bins0, alpha=0.5)
axcolor = 'lightgray'
axmean = plt.axes([0.25, 0.01, 0.65, 0.03], axisbg=axcolor)
axstd = plt.axes([0.25, 0.06, 0.65, 0.03], axisbg=axcolor)
axssize = plt.axes([0.25, 0.11, 0.65, 0.03], axisbg=axcolor)
smean = Slider(axmean, 'Mean', -5, 5, valinit=m0)
sstd = Slider(axstd, 'Std', 0.1, 10.0, valinit=std0)
sn = Slider(axssize, 'n_sample', 10, 10000, valinit=n0)
smean.on_changed(update)
sstd.on_changed(update)
sn.on_changed(update)
plt.show()
For creating the Histogram in Matplotlib we use hist() function which belongs to pyplot module. For plotting two histograms together, we have to use hist() function separately with two datasets by giving some settings.
We can achieve this by increasing the number of bins, which is essentially the number of classes the histogram divides the data into. More bins will make the histogram smoother.
One option is to clear the axis and just replot the histogram. The other option, more in the spirit of l.set_value
approach of the matplotlib slider example would be to generate the histogram data with numpy, use a bar chart and update this using bar.set_height
and bar.set_x
with a rescale on the axis. The complete example is then:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def update(val):
mv = smean.val
stdv = sstd.val
n_sample = round(sn.val)
nd = np.random.normal(loc=mv, scale=stdv, size=n_sample)
#Update barchart height and x values
hist, bins = np.histogram(nd, normed=True, bins=n_bins0)
[bar.set_height(hist[i]) for i, bar in enumerate(b)]
[bar.set_x(bins[i]) for i, bar in enumerate(b)]
ax.relim()
ax.autoscale_view()
plt.draw()
def reset(event):
mv.reset()
stdv.reset()
n_sample.reset()
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
m0 = -2.5
std0 = 1
n0 = 1000
n_bins0 = 20
nd = np.random.normal(m0, std0, n0)
hist, bins = np.histogram(nd, normed=True, bins=n_bins0)
b = plt.bar(bins[:-1], hist, width=.3)
axcolor = 'lightgray'
axmean = plt.axes([0.25, 0.01, 0.65, 0.03], axisbg=axcolor)
axstd = plt.axes([0.25, 0.06, 0.65, 0.03], axisbg=axcolor)
axssize = plt.axes([0.25, 0.11, 0.65, 0.03], axisbg=axcolor)
smean = Slider(axmean, 'Mean', -5, 5, valinit=m0)
sstd = Slider(axstd, 'Std', 0.1, 10.0, valinit=std0)
sn = Slider(axssize, 'n_sample', 10, 10000, valinit=n0)
smean.on_changed(update)
sstd.on_changed(update)
sn.on_changed(update)
plt.show()
UPDATE:
Version using clear axis (ax.cla()
) and redraw ax.hist(...)
,
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def update(val):
mv = smean.val
stdv = sstd.val
n_sample = round(sn.val)
nd = np.random.normal(loc=mv, scale=stdv, size=n_sample)
#Redraw histogram
ax.cla()
ax.hist(nd, normed=True, bins=n_bins0, alpha=0.5)
plt.draw()
def reset(event):
mv.reset()
stdv.reset()
n_sample.reset()
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
m0 = -2.5
std0 = 1
n0 = 1000
n_bins0 = 20
nd = np.random.normal(m0, std0, n0)
plt.hist(nd, normed=True, bins=n_bins0, alpha=0.5)
axcolor = 'lightgray'
axmean = plt.axes([0.25, 0.01, 0.65, 0.03], axisbg=axcolor)
axstd = plt.axes([0.25, 0.06, 0.65, 0.03], axisbg=axcolor)
axssize = plt.axes([0.25, 0.11, 0.65, 0.03], axisbg=axcolor)
smean = Slider(axmean, 'Mean', -5, 5, valinit=m0)
sstd = Slider(axstd, 'Std', 0.1, 10.0, valinit=std0)
sn = Slider(axssize, 'n_sample', 10, 10000, valinit=n0)
smean.on_changed(update)
sstd.on_changed(update)
sn.on_changed(update)
plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With