holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.78k stars 518 forks source link

Implement a nested dropdown select #5744

Closed ahuang11 closed 3 months ago

ahuang11 commented 1 year ago

Can we have something like a nested, n-dim select dropdown built-in to Panel widgets? (I vaguely remember seeing @jlstevens implement this somewhere?)

import panel as pn
pn.extension()

WX_VARS_LEVS = {"precip": [1000], "temp": [1000, 925, 700, 500, 300], "vorticity": [500, 300]}
WX_VARS = list(WX_VARS_LEVS.keys())

def update_lev_select(var):
    return pn.widgets.Select(options=WX_VARS_LEVS[var])

var_select = pn.widgets.Select(options=WX_VARS)
lev_select = pn.bind(update_lev_select, var=var_select)
pn.Column(var_select, lev_select)
image image

Not sure if it's enough to support just one level, but for multiple levels, I imagine a dict of dict of list? {"precip": {"conus": [1000], "global": [1000]}, "temp": {"conus": [1000, 925, 700, 500, 300], "global": {"temp": [1000, 500]}}}

Here's an applicable example of multi-level dropdowns:

  1. Product
  2. Layer
  3. Time (potentially 4. Level) image
MarcSkovMadsen commented 1 year ago

Very often the data you have is not a dict, but a dataframe

ahuang11 commented 1 year ago

To be consistent with other widgets, I like the idea of keeping dict, list. (I suppose Tabulator/Perspective uses param.DataFrame)

Also, I think transforming a dataframe to a dict is semi-trivial df.to_dict()

I wonder how a dataframe with multi-level would look.

philippjfr commented 1 year ago

Usually you'd have a multi-index that maps to the dict. I'm fine with a .from_index() method or similar.

philippjfr commented 1 year ago

Generally I've always wanted a .from_pandas method for most widgets that automatically computes the bounds for sliders and the options for select widgets.

MarcSkovMadsen commented 1 year ago

To be consistent with other widgets, I like the idea of keeping dict, list. (I suppose Tabulator/Perspective uses param.DataFrame)

Also, I think transforming a dataframe to a dict is semi-trivial df.to_dict()

I wonder how a dataframe with multi-level would look.

Its not just transforming a dataframe to a dictionary. You might have a DataFrame with 10mn rows containing categorical columns category1, category2, category3 and other columns. You then want to select first from the unique category1 values. Then from the reduced set of unique category2 values under category1 etc.

ahuang11 commented 1 year ago

So I suppose this widget should definitely support n-nesting, and I agree that I prefer from_pandas or from_index instead of a param.DataFrame field.

ahuang11 commented 1 year ago

I can try creating a prototype. Would this be a CompositeWidget?

benbarn313 commented 1 year ago

One thing to note is that it would be nice to have some more complex dependencies. For example you could have one widgets contents be dependent on two independent widgets.

ahuang11 commented 1 year ago

Interesting idea; not entirely clear how to express that as a Python type--perhaps tuples as keys?

{("temperature", 1000): [*times], ("temperature", 500): [*other_times]}

or actually is that the same as {"temperature": {"1000": [*times], "500": [*other_times]}}

Ah I understand, it's two separate widgets simultaneously shown...

File Type + Variable -> Levels -> Times vs File Type -> Variable -> Levels -> Times

However, is it necessary to show both simultaneously?

If so, is it within the scope of this widget or separate?

legout commented 6 months ago

Although this feature is already merged, I want to ask, if this could be extended to Multiselect.