Hi, I want to create a class which has a param.Integers
attribute for each name in a list (columns = [‘bike’,‘car’,‘plane’,‘train’]
).If I hardcode the attributes and the depends
names it works, but this is not flexible. See screenshot and code underneath.
How can I implement this given only the list of attribute names? I’ve tried some approaches but failed: see lower…
This figure shows what I want
This code is not ideal/flexible
class MultiParameter(param.Parameterized):
columns = ['bike','car','plane','train']
bike = param.Integer(default=4,bounds=(1,10))
car = param.Integer(default=4,bounds=(1,10))
plane = param.Integer(default=4,bounds=(1,10))
train = param.Integer(default=4,bounds=(1,10))
plot_vars = param.ListSelector(default=columns[:1],
objects=columns)
data_par = param.DataFrame(pd.DataFrame(data=np.random.rand(100,4),
columns=columns))
@pn.depends('plot_vars','bike','car','plane','train')
def plot_compare(self):
layouts = []
for var in self.plot_vars:
scatter = self.data_par.hvplot.scatter(y=var,label=var)
hlines = [hv.HLine(qi) for qi in self.get_quantiles(var)]
scatterandlines = hv.Overlay([scatter]+hlines).opts(show_legend=False)
layouts.append(scatterandlines)
return hv.Layout(layouts).cols(2)
def get_quantiles(self,var):
val = eval(f'self.{var}')
return self.data_par[var].quantile([(ii+.5)/val for ii in range(val)])
def layout(self):
return pn.Column(pn.Row(pn.Param(self.param['plot_vars']),
pn.Param(self,parameters=self.plot_vars,show_name=False)),
self.plot_compare)
These two approaches aren’t working for me:
1. separate class & objects
Create a separate Parameterized class
Bin
class Bin(param.Parameterized):
value = param.Integer(4,bounds=(1,10))
columns = ['bike','car','plane','train']
mybins = [Bin(name=x) for x in columns]
add ObjectSelector with list of Bin objects
class MultiParameter(param.Parameterized):
...
bin_var = param.ObjectSelector(default=mybins[0],objects=mybins)
....
@pn.depends('bin_var.param','bin_var', watch=True)
def some_function(self):
Issue!
I fail to link the parameter changes on the Bin objects
and not very neat.
2. add a param.Parametrized_class
object (seemed promising: Programatically create Param Classes - #2 by AurelienSciarra)
class MultiParameter(param.Parameterized):
...
mybins = param.parameterized_class('mybins',
{var:param.Integer(default=4,
bounds=(1,10)) for var in columns})
....
seems to work as a param object…
m=MultiParameter()
pn.Param(m.mybins)
…but fails when I use it in another method/panel.
Issue! fails on:
RecursionError: maximum recursion depth exceeded while calling a Python object
which crashes my notebook
So to summarize: How can I programmatically add attributes in a Param
class?
Thanks in advance for thinking about this.