Repository: holoviz/hvplot

Issue:
pn.widgets not working in a list 
Hi, I'm trying out the hvplot .interactive.  I got TypeError: 'RadioButtonGroup' object is not callable for the following code, I think it's because I can't write my xaxis in a list.  It works if I change  `.groupby(['origin', xaxis])` to  `.groupby(xaxis)`, but it'd be nice if `pn.widgets` can work in a list.  I'd really appreciate some help. Thanks!

```
from bokeh.sampledata.autompg import autompg_clean as df
import hvplot.pandas
import panel as pn
import holoviews as hv
hv.extension('bokeh')
idf = df.interactive()
cylinders = pn.widgets.IntSlider(start=4, end=8, step=2)
mfr = pn.widgets.ToggleGroup(options=['ford', 'chevrolet', 'plymouth', 'honda', 'sbaru', 'volkswagen'], 
                             value=['ford', 'chevrolet', 'plymouth', 'honda', 'sbaru', 'volkswagen'])
xaxis = pn.widgets.RadioButtonGroup(name='X axis', options=['mpg', 'yr'])
yaxis = pn.widgets.RadioButtonGroup(name='Y axis', options=['hp', 'weight'])

ipipeline = (
    idf[
        (idf.cyl == cylinders) & 
        (idf.mfr.isin(mfr))
    ]
    .groupby(['origin', xaxis])[yaxis].mean()
    .to_frame()
    .reset_index()
)
```
![image](https://user-images.githubusercontent.com/39501859/149612344-adc89c0b-c654-48fe-a25d-4c0a25842e40.png)


<details>
<summary>Traceback</summary>

```python-traceback
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/n9/dr352bs550nck1fg2mz9vpn80000gn/T/ipykernel_46537/1739249479.py in <module>
     12 
     13 ipipeline = (
---> 14     idf[
     15         (idf.cyl == cylinders) &
     16         (idf.mfr.isin(mfr))

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/hvplot/interactive.py in __call__(self, *args, **kwargs)
    185                                        accessor=True)
    186             kwargs = dict(self._inherit_kwargs, **kwargs)
--> 187             clone = self._clone(method(*args, **kwargs), plot=self._method == 'plot')
    188         finally:
    189             self._method = None

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/hvplot/interactive.py in _clone(self, transform, plot, loc, center, dmap, **kwargs)
    114         depth = self._depth+1
    115         kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs))
--> 116         return type(self)(self._obj, transform, plot, depth,
    117                           loc, center, dmap, **kwargs)
    118 

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/hvplot/interactive.py in __init__(self, obj, transform, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, **kwargs)
     84         self._kwargs = kwargs
     85         ds = hv.Dataset(self._obj)
---> 86         self._current = self._transform.apply(ds, keep_index=True, compute=False)
     87         self._init = True
     88 

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/holoviews/util/transform.py in apply(self, dataset, flat, expanded, ranges, all_values, keep_index, compute, strict)
    736             drange = ranges.get(eldim, {})
    737             drange = drange.get('combined', drange)
--> 738             data = self._apply_fn(dataset, data, fn, fn_name, args,
    739                                   kwargs, accessor, drange)
    740         drop_index = keep_index_for_compute and not keep_index

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/holoviews/util/transform.py in _apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
    634                         data = method(*args, **kwargs)
    635                     else:
--> 636                         raise e
    637         else:
    638             data = fn(*args, **kwargs)

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/holoviews/util/transform.py in _apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
    628             else:
    629                 try:
--> 630                     data = method(*args, **kwargs)
    631                 except Exception as e:
    632                     if 'axis' in kwargs:

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/frame.py in groupby(self, by, axis, level, as_index, sort, group_keys, squeeze, observed, dropna)
   7624         # error: Argument "squeeze" to "DataFrameGroupBy" has incompatible type
   7625         # "Union[bool, NoDefault]"; expected "bool"
-> 7626         return DataFrameGroupBy(
   7627             obj=self,
   7628             keys=by,

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/groupby/groupby.py in __init__(self, obj, keys, axis, level, grouper, exclusions, selection, as_index, sort, group_keys, squeeze, observed, mutated, dropna)
    886             from pandas.core.groupby.grouper import get_grouper
    887 
--> 888             grouper, exclusions, obj = get_grouper(
    889                 obj,
    890                 keys,

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/groupby/grouper.py in get_grouper(obj, key, axis, level, sort, observed, mutated, validate, dropna)
    875         # allow us to passing the actual Grouping as the gpr
    876         ping = (
--> 877             Grouping(
    878                 group_axis,
    879                 gpr,

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/groupby/grouper.py in __init__(self, index, grouper, obj, level, sort, observed, in_axis, dropna)
    533                 raise ValueError(f"Grouper for '{t}' not 1-dimensional")
    534 
--> 535             self.grouping_vector = index.map(self.grouping_vector)
    536 
    537             if not (

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/indexes/base.py in map(self, mapper, na_action)
   5505         from pandas.core.indexes.multi import MultiIndex
   5506 
-> 5507         new_values = self._map_values(mapper, na_action=na_action)
   5508 
   5509         attributes = self._get_attributes_dict()

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/core/base.py in _map_values(self, mapper, na_action)
    868 
    869         # mapper is a function
--> 870         new_values = map_f(values, mapper)
    871 
    872         return new_values

/opt/anaconda3/envs/p39/lib/python3.9/site-packages/pandas/_libs/lib.pyx in pandas._libs.lib.map_infer()

TypeError: 'RadioButtonGroup' object is not callable
```
</details>


Discussion:
Hi @sophiamyang . 

- Could you update the code example to make it runnable. Right now imports are missing.
- Could you take a screen shot of error? It can sometimes help understand the context of the problem and provide more assurance that there is a real, reproducible problem.

Thanks.
Thanks @MarcSkovMadsen, I updated the code example and added the error message. 
So I have made a somewhat working example of this problem as far as I can see (correct me if I'm wrong).

### The example

<details>
  <summary>The code</summary>

``` python
import holoviews as hv
import hvplot.pandas  # noqa
import panel as pn
from bokeh.sampledata.autompg import autompg_clean as df

hv.extension("bokeh")

idf = df.interactive()
cylinders = pn.widgets.IntSlider(start=4, end=8, step=2)
mfr = pn.widgets.ToggleGroup(
    options=["ford", "chevrolet", "plymouth", "honda", "sbaru", "volkswagen"],
    value=["ford", "chevrolet", "plymouth", "honda", "sbaru", "volkswagen"],
)
xaxis = pn.widgets.RadioButtonGroup(name="X axis", options=["mpg", "yr"])
yaxis = pn.widgets.RadioButtonGroup(name="Y axis", options=["hp", "weight"])

ipipeline = (
    idf[(idf.cyl == cylinders) & (idf.mfr.isin(mfr))]
    .groupby(["origin", xaxis])[yaxis]
    .mean()
    .to_frame()
    .sort_values(xaxis)
    .reset_index()
)

pn.Column(ipipeline.hvplot(x=xaxis, y=yaxis, by="origin"), ipipeline.output(), sizing_mode="stretch_both").servable()
```

</details>

https://user-images.githubusercontent.com/19758978/149788435-c0042ebc-eac5-4511-ac4e-6f66a74fec20.mp4


### Changes
I have made this change in holoviews to get this example to work. 

https://github.com/holoviz/holoviews/blob/cc6b27f01710402fdfee2aeef1507425ca78c91f/holoviews/util/transform.py#L579-L606

Where I have added this to the if statement for argument and keyword arguments , respectively:
``` python
elif isinstance(arg, (list, tuple)):
    arg = [resolve_dependent_value(a) for a in arg]
```
``` python
elif isinstance(v,  (list, tuple)):
    v = [resolve_dependent_value(a) for a in v]
```
Both is done to convert the widget into an actual value. 

### Problems
There is some problems I have noticed:

- The plot is not updating when changing the cylinder slider, but it updates the DataFrame.
- I can't disable "volkswagen" in the `ToggleGroup`.

Edit 1: Updated with better changes and removed a problem.
The reason why is the plot is not updating when I change the cylinder slider is that both it and the mfr toggle group have no name. This means that if I change the order of them in the ipipeline it is the toggle group which becomes unresponsive. If I give one of the widget a name both of them will work. This should be fixed upstream in holoviews to avoid it overwriting widgets with no (or the same name).
 
Thanks so much @Hoxbro!
No problem, glad I could help - so you're able to share with the world how awesome the holoviz stack is.

For the last of the problems about how I can't disable "volkswagen". It is because a HSpacer is blocking it and if i add `pn.extension(sizing_mode="stretch_width")` I'm able to click on it.

Resolving patch:
diff --git a/hvplot/interactive.py b/hvplot/interactive.py
--- a/hvplot/interactive.py
+++ b/hvplot/interactive.py
@@ -20,6 +20,7 @@
 def _find_widgets(op):
     widgets = []
     op_args = list(op['args'])+list(op['kwargs'].values())
+    op_args = hv.core.util.flatten(op_args)
     for op_arg in op_args:
         if 'panel' in sys.modules:
             if isinstance(op_arg, Widget) and op_arg not in widgets:


Test patch: