PlotControlWidget

When there is tabular data associated to a data map there can be more different features in the tabular data than can easily be dispalyed via colour, marker size etc. In such cases it can be useful to be able to select different features to colour points by, or adjust marker sizes accordingly. While one could generate many different PlotPanes with each such combination of colour and marker size, it would be best to be able to interactively select these for a given PlotPane. The PlotControlWidget makes this possible. We will outline the core functionality of a PlotControlWidget and how to connect it to a PlotPane.

The first step is to load thisnotthat and panel.

[1]:
import thisnotthat as tnt
import panel as pn

To make Panel based objects interactive within a notebook we need to load the panel extension.

[2]:
pn.extension()

Now we need some data to use as an example. In this case we’ll use the Palmer’s Penguins dataset, which we can get easy access to via seaborn; we will also clean up the data and rename the columns for ease of use.

[3]:
import seaborn as sns

penguins = (
    sns.load_dataset('penguins')
    .dropna()
    .rename(
        columns={
            "bill_length_mm": "bill-length",
            "bill_depth_mm": "bill-depth",
            "flipper_length_mm": "flipper-length",
            "body_mass_g": "body-mass"
        }
    )
)

The penguins dataset consists of a series of measurements relating to three species of penguins (Adelie, Chinstrap, and Gentoo) found in three different islands (Torgersen, Biscoe and Dream) in the Antarctic. We can glance at the first few rows to get a sense of the data.

[4]:
penguins.head()
[4]:
species island bill-length bill-depth flipper-length body-mass sex
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 Male
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 Female
2 Adelie Torgersen 40.3 18.0 195.0 3250.0 Female
4 Adelie Torgersen 36.7 19.3 193.0 3450.0 Female
5 Adelie Torgersen 39.3 20.6 190.0 3650.0 Male

To create a PlotControlWidget we simply need to pass it a dataframe of data that can be used to colour, size, or provide hover text, for a PlotPane. In this case that is simply the penguins dataframe.

[5]:
controller = tnt.PlotControlWidget(penguins)
controller
[5]:

The PlotControlWidget offers several drop-down selections, allowing the choice of a colour palette, a feature to colour by, a feature to determine marker sizes, and a feature to use for hover text tooltips. Finally there is a button to apply the changes – allowing several options to be selected before pushing the choices to the plot. Each drop down has an associated Param that can be accessed.

[6]:
controller.color_by_vector

To see how this can be used to interact with a plot we’ll need a data map. For that we’ll need some preprocessing for the numeric columns of the penguins data, and UMAP.

[7]:
from sklearn.preprocessing import RobustScaler
import umap

We can now build a data map out of the rescaled numeric penguins data, and create a PlotPane for it.

[8]:
data_for_umap = RobustScaler().fit_transform(penguins.select_dtypes(include="number"))
penguin_datamap = umap.UMAP(random_state=42).fit_transform(data_for_umap)
plot = tnt.BokehPlotPane(
    penguin_datamap,
    labels=penguins.species,
    hover_text=penguins.island,
    width=400,
    height=400,
    legend_location="top_right",
    title="Penguins data map",
)

A quick visual check shows that our PlotPane data map looks like the sort of thing we want.

[9]:
plot.pane
[9]:

To have the controller interact with the plot we need to link the relevant params together. This can be most easily done via the link_to_plot method of the PlotControlWidget. Alternatively more fine grained control can be arranged using the link methjod common to all panel Panes and Widgets. We’ll use link_to_plot for convenience.

[10]:
controller.link_to_plot(plot)
pn.Row(plot, controller)
[10]:

If running in a notebook you can now select palettes and color the data by different columns of the metadata, or adjust the marker size and hover text using the various drop downs in the PlotControlWidget. This makes it easy to see, for example, how various specific features, such as body-mass, or flipper-length vary over the map, or look at other categorical information such as which island the data was sampled from.

If you want a little more control the PlotControlWidget the scale_type_selector parameter allows the addition of a selection of different scale types for potentially numeric data – whether to use a linear scale (the default) or a log scale, or even a square-root scale (often useful for marker sizes). Note that log and square-root scales are not valid for data columns that are non-numeric, or contain negative values.

[11]:
controller = tnt.PlotControlWidget(penguins, scale_type_selector=True)
controller.link_to_plot(plot)
pn.Row(plot, controller)
[11]:
[ ]: