如何解决使用参数值的滑块创建连续均匀分布的交互式绘图
如何使用 python 创建 Continuous Uniform Distribution 的 pdf 和 cdf 的交互式绘图?
我想要交互式滑块,我可以用它来调整分布的参数。
这有助于更好地了解此分布对其不同参数值的行为。
解决方法
1.最简单的方法是使用 scipy.stats.uniform() 获取分布的 pdf 和 cdf,然后使用 pn.interact() 获取参数的交互式滑块:
# import libraries
from scipy import stats
import pandas as pd
import hvplot.pandas
import panel as pn
pn.extension()
import panel.widgets as pnw
import holoviews as hv
hv.extension('bokeh')
# define pdf and cdf for cont uniform distr and return plots
def get_interactive_plot_cont_uniform(loc=1,scale=5):
continuous_uniform = stats.uniform(loc=loc,scale=scale)
x_values = np.linspace(0,10,num=1000)
fx_values = continuous_uniform.pdf(x_values)
Fx_values = continuous_uniform.cdf(x_values)
interactive_plot = (
hv.Curve((x_values,fx_values),label='PDF')
+ hv.Curve((x_values,Fx_values),label='CDF'))
return interactive_plot
# use pn.interact() to get interactive sliders
# and define the sliders yourself for more flexibility
pn.interact(
get_interactive_plot_cont_uniform,loc=pnw.FloatSlider(
name='Value for loc',value=1.,start=0,step=0.5,end=10),scale=pnw.FloatSlider(
name='Value for scale',value=5.,)
产生的带有滑块的交互式绘图:
2.一个更广泛、更灵活的例子,它允许更直观地设置参数 a 和 b:
# create sliders to adjust parameter a and b
param_a = pnw.FloatSlider(name='Value for parameter a',end=10)
param_b = pnw.FloatSlider(name='Value for parameter b',value=6.,end=10)
# get interactivity by using following decorator
@pn.depends(param_a,param_b)
def get_interactive_cont_uniform(param_a,param_b):
# define the uniform distribution
# scale in scipy.stats.uniform is b - a
loc = param_a
scale = param_b - param_a
continuous_uniform = stats.uniform(loc=loc,scale=scale)
# calculate x and y values for pdf and cdf and put in dataframe
x_values = np.linspace(0,num=1000)
fx_values = continuous_uniform.pdf(x_values)
Fx_values = continuous_uniform.cdf(x_values)
df = pd.DataFrame({
'x': x_values,'f(x)': fx_values,'F(x)': Fx_values,})
# create pdf and cdf plot
pdf_plot = df.hvplot.line(
x='x',y='f(x)',ylim=(0,1.02),ylabel='f(x) - pdf values',xlabel='',title=f'pdf where a={param_a} and b={param_b}',height=225,).opts(fontscale=1.25)
cdf_plot = df.hvplot.line(
x='x',y='F(x)',ylabel='F(x) - cdf values',title=f'cdf where a={param_a} and b={param_b}',).opts(fontscale=1.25)
return (pdf_plot + cdf_plot).cols(1)
# use pyviz panel to get a nice view of sliders and the plots
pn.Column(
pn.pane.Markdown("## Continuous Uniform Distribution"),pn.Row(param_a,param_b),pn.Row(get_interactive_cont_uniform)
)
,
要建立在另一个答案的基础上,您还可以使用 panel
实现的面向类的方法。这是我最喜欢的方法,因为它使您的代码保持良好和模块化。此外,它直接通过 bokeh
绘图,而不是通过 holoviews
(我个人一般对此持怀疑态度)。使用 bokeh
而不是 holoviews
可以让您更好地控制您的情节,但对于这些目的,您选择哪条路线并不重要。
此代码段在笔记本中工作,但可以通过将 .show()
方法的调用更改为 .servable()
并使用以下命令从命令行/终端运行脚本来适应脚本格式:panel serve file.py --show
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
import panel as pn
import param
from scipy import stats
class UniformViewer(param.Parameterized):
a = param.Number(1,bounds=(0,15),step=.5)
b = param.Number(4,step=.5,inclusive_bounds=(False,True))
def __init__(self,**params):
super().__init__(**params)
# Initialize 2 plots with common arguments
plot_kwargs = {
"height": 250,"width": 250,"y_range": (-.1,1.1)
}
self.p_pdf = figure(title="PDF",**plot_kwargs)
self.p_cdf = figure(title="CDF",**plot_kwargs)
# Calculate range of data based on parameter bounds
a_min,a_max = self.param.a.bounds
b_min,b_max = self.param.b.bounds
# Create x-values for pdf/cdf calculations
x_min,x_max = min(a_min,b_min),max(a_max,b_max)
self.x = np.linspace(x_min,x_max,1000)
# store x values in our CDS since they won't change
self.cds = ColumnDataSource({"x": self.x})
self.update_cds() # Populate cdf/pdf values into the CDS before plotting
# Draw our pdf and cdf on their respective figures
self.p_pdf.line(x="x",y="pdf",source=self.cds)
self.p_cdf.line(x="x",y="cdf",source=self.cds)
# Add callback that executes anytime self.a or self.b changes
@param.depends("a","b",watch=True)
def update_cds(self):
# Calcualte the uniform distribution using
# self.a as the left endpoint and self.b as the right endpoint
uniform_dist = stats.uniform(loc=self.a,scale=self.b-self.a)
self.cds.data.update({
"pdf": uniform_dist.pdf(self.x),"cdf": uniform_dist.cdf(self.x)
})
def view(self):
return pn.Row(self.p_pdf,self.p_cdf)
interactive_plot = UniformViewer()
pn.Column(interactive_plot,interactive_plot.view()).show()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。