holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.06k stars 103 forks source link

Add API to create ridge / joy plots? #1342

Open maximlt opened 3 months ago

maximlt commented 3 months ago

The subcoordinate_y feature added to HoloViews opens the door to the implementation of ridge / joy plots in hvPlot. I'm opening this issue to gauge the interest in this feature and discuss it.

HoloViews code (stolen from Demetris'!)

```python import numpy as np import holoviews as hv from scipy.stats import gaussian_kde hv.extension('bokeh') categories = ['A', 'B', 'C', 'D', 'E'] data = {cat: np.random.normal(loc=i-2, scale=1.0, size=100) for i, cat in enumerate(categories)} x = np.linspace(-5, 5, 100) curves = [] areas = [] for i, (cat, values) in enumerate(data.items()): pdf = gaussian_kde(values)(x) area = hv.Area((x, pdf), label=cat).opts( subcoordinate_y=True, subcoordinate_scale=1.5, ) areas.append(area) ridge_plot_areas = hv.Overlay(areas).opts( width=900, height=400, ) ridge_plot_areas.opts(show_legend=False) ```

image

Python users can already create such plots using the usual plotting libraries, albeit usually by having to resort to low-level APIs:

I also found two packages implementing high-level APIs:

And a few other packages from other ecosystems:

(https://github.com/holoviz/hvplot/issues/1160 should be implemented first)

droumis commented 1 month ago

Is this theoretical joyplot API separate or the same API as would support a multi-chan timeseries plot? I think they are probably different.

maximlt commented 1 month ago

Note to self. For a little while I got confused with what exactly a ridgeplot is, trying to adapt it to fit and replace subcoordinate_y. However, a ridgeplot most often is an overlay of kde plots, this is the output this API should offer.

import pandas as pd
import numpy as np
import hvplot.pandas

df = pd.DataFrame(np.random.random((1000, 4)), columns=list("ABCD"))
df.hvplot.ridge()  # somewhat better version of `df.hvplot.kde(subcoordinate_y={'subcoordinate_scale': 2})`

image