Skip to content

Make it easy to use DataFrame with NestedSelect #6604

@MarcSkovMadsen

Description

@MarcSkovMadsen

The new NestedSelect will be really useful. But 100% of my use cases starts with a Pandas Dataframe. And its currently not very clear how to use that with NestedSelect.

I would recommend either

  • Documenting how to convert categorical columns of a DataFrame to options.
  • Provide one or more methods to easily create a NestedSelect from a dataframe.

Personally I would strongly recommend the second option. I would suggest adding class methods similar to get_options_from_dataframe and create_from_dataframe to the NestedSelect.

Example Code

import panel as pn
from bokeh.sampledata.autompg import autompg_clean
import pandas as pd

def _build_nested_dict(df, depth=0, max_depth=None):
    if max_depth is None:
        max_depth = len(df.columns)
    
    # Base case: if depth reaches the last column before values
    if depth == max_depth - 1:
        return df[df.columns[depth]].tolist()
    
    # Recursive case: build dictionary at current depth
    nested_dict = {}
    for value in df[df.columns[depth]].unique():
        filtered_df = df[df[df.columns[depth]] == value]
        nested_dict[value] = _build_nested_dict(filtered_df, depth + 1, max_depth)
    return nested_dict

def get_options_from_dataframe(df, cols=None):
    if not cols:
        cols = list(df.columns)

    df = df[cols].drop_duplicates().sort_values(cols).reset_index(drop=True)
    options = _build_nested_dict(df)
    return options

def test_get_options_from_dataframe():
    data = {
        'continent': ['Europe', 'Europe', 'Asia', 'Asia', 'North America'],
        'country': ['France', 'France', 'Japan', 'Japan', 'USA'],
        'manufacturer': ['Fiat', 'Peugeot', 'Toyota', 'Nissan', 'Ford'],
        'model': ['500', '208', 'Corolla', 'Sentra', 'Mustang']
    }
    df = pd.DataFrame(data)
    options = get_options_from_dataframe(df)
    print(options)

test_get_options_from_dataframe()

def create_from_dataframe(df, cols=None, **params):
    if not cols:
        cols = list(df.columns)

    options = get_options_from_dataframe(df, cols)
    params["levels"]=params.get("levels", cols)
    return pn.widgets.NestedSelect(options=options, **params)


cols = ["origin", "mfr", "name", ]
import panel as pn

pn.extension()

select=create_from_dataframe(autompg_clean, cols=cols, levels=["Origin", "Manufacturer", "Name"])
select.servable()
nested-select.mp4

Additional Question

Is there some relation to hvPlot/ HoloViews widgets? When you use groupby option in hvPlot it must do something similar?

[x] Yes. I would be willing to provide a PR if the proposal is accepted by Philipp.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions