dataframepanelgeopandasgeoviews

geoviews select widget to color by column in geopandas dataframe


I have a geoviews map that shows points from my geopandas dataframe. I would like to use panel to create a select widget to color the map by one of the columns, as I have done with pandas dataframes and hvplot.

Example object

import random

import geopandas as gpd
import geoviews as gv

df = gpd.read_file(gpd.datasets.get_path('naturalearth_cities'))
# create some columns of random data
df['A'] = [random.randrange(1, 50, 1) for i in range(len(df))]
df['B'] = [random.randrange(200, 300, 1) for i in range(len(df))]

The code in this snippet creates a map, but the color argument is hard coded:

poly_plot = gv.Points(df).opts(color='A', width=600, height=600, colorbar=True, clabel='A',
                               cmap='inferno', size=12)

gv.tile_sources.OSM * poly_plot

Output of the working plot

However, when I attempt to add a widget select for the color dropdown using panel I get an error:

# create the select widget
columns = pn.widgets.Select(name='columns', options=['A', 'B'])
# create my geoviews object, specifying my select widget for color
poly_plot = gv.Points(df).opts(color=columns, width=600, height=600, colorbar=True, 
clabel='A', cmap='inferno', size=12)
# plot on a basemap
gv.tile_sources.OSM * poly_plot

The error:

ValueError [Call holoviews.ipython.show_traceback() for details] failed to validate Scatter(id='p2448', ...).fill_color: expected an element of either String, Nullable(Color), Instance(Value), Instance(Field), Instance(Expr), Struct(value=Nullable(Color), transform=Instance(Transform)), Struct(field=String, transform=Instance(Transform)) or Struct(expr=Instance(Expression), transform=Instance(Transform)), got Select(name='columns', options=['A', 'B'], value='A')

The output of holoviews.ipython.show_traceback() is long so I didn't post it, but I'm happy to add if it's helpful.

The select widget seems to get created correctly, but I can't get it connected to the plot (error above).

column selection widget

Thank you!


Solution

  • You could add the columns (A and B) as a dim and make a callable to update the layout/map :

    import panel as pn
    from geoviews import dim, opts
    
    def update(col):
        return gv.Points(
            df,
        ).opts(
            opts.Points(
                width=800,
                height=500,
                colorbar=True,
                cmap="inferno",
                size=12,
                color=dim(col),
            )
        )
    
    csel = pn.widgets.Select(options=["A", "B"], value="A")
    
    @pn.depends(col=csel.param.value)
    def plot(col):
        return gv.tile_sources.OSM * update(col)
    
    pn.Column(csel, plot).show()
    

    Output (at localhost):

    enter image description here