Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add subcoordinate_y keyword #1379

Merged
merged 5 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/user_guide/Customization.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@
" rot: number\n",
" Rotates the axis ticks along the x-axis by the specified\n",
" number of degrees.\n",
" subcoordinate_y: bool or dict\n",
" Whether to enable sub-coordinate y systems for this plot. Accepts also a\n",
" dictionary of related options to pass down to HoloViews,\n",
" e.g. `{'subcoordinate_scale': 2}`.\n",
" shared_axes (default=True): boolean\n",
" Whether to link axes between plots\n",
" transforms (default={}): dict\n",
Expand Down
27 changes: 27 additions & 0 deletions doc/user_guide/Timeseries_Data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import hvplot.pandas # noqa\n",
"from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature as sst\n",
"\n",
Expand Down Expand Up @@ -84,6 +85,32 @@
"sst.hvplot(autorange=\"y\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Subcoordinate y-axis\n",
"\n",
"hvPlot enables you to create overlays where each element has its own distinct y-axis subcoordinate system, which is particularly useful to analyse multiple timeseries. To activate this feature that automatically distributes overlay elements along the y-axis, set the `subcoordinate_y` keyword to `True`. `subcoordinate_y` also accepts a dictionary of related options, for example set `subcoordinate_y={'subcoordinate_scale': 2}` to increase the scale of each sub-plot, resulting in each curve's vertical range overlapping 50% with its adjacent elements. Additionally, the y-axis wheel-zoom will apply to each curve's respective sub-coordinate y-axis, rather than the global coordinate frame. More information about this feature can be found in [HoloViews' documentation](https://holoviews.org/user_guide/Customizing_Plots.html#subcoordinate-y-axis)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For demonstration purposes, we'll temporarily add a new column of 'sensors' that splits up the temperature data into several series."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sensor = np.random.choice(['s1', 's2', 's3', 's4'], size=len(sst))\n",
"sst.assign(sensor=sensor).hvplot(by='sensor', subcoordinate_y=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
11 changes: 11 additions & 0 deletions hvplot/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ class HoloViewsConverter:
rot: number
Rotates the axis ticks along the x-axis by the specified
number of degrees.
subcoordinate_y: bool or dict
Whether to enable sub-coordinate y systems for this plot. Accepts also a
dictionary of related options to pass down to HoloViews,
e.g. `{'subcoordinate_scale': 2}`.
shared_axes (default=True): boolean
Whether to link axes between plots
transforms (default={}): dict
Expand Down Expand Up @@ -398,6 +402,7 @@ class HoloViewsConverter:
'data_aspect',
'fontscale',
'bgcolor',
'subcoordinate_y',
]

_style_options = [
Expand Down Expand Up @@ -589,6 +594,7 @@ def __init__(
features=None,
rescale_discrete_levels=None,
autorange=None,
subcoordinate_y=None,
**kwds,
):
# Process data and related options
Expand Down Expand Up @@ -730,6 +736,11 @@ def __init__(
'The legend option should be a boolean or '
f'a valid legend position (i.e. one of {list(self._legend_positions)}).'
)
if subcoordinate_y:
plot_opts['subcoordinate_y'] = True
if isinstance(subcoordinate_y, dict):
plot_opts.update(subcoordinate_y)

plotwds = [
'xticks',
'yticks',
Expand Down
15 changes: 15 additions & 0 deletions hvplot/tests/testoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,18 @@ def test_cticks(self, da2):
plot = da2.isel(other=0).hvplot(cticks=[5, 10])
handles = hv.renderer('bokeh').get_plot(plot).handles
assert handles['colorbar'].ticker.ticks == [5, 10]


def test_subcoordinate_y_bool(load_pandas_accessor):
df = pd.DataFrame(np.random.random((10, 3)), columns=list('ABC'))
plot = df.hvplot.line(subcoordinate_y=True)
opts = Store.lookup_options('bokeh', plot, 'plot')
assert opts.kwargs['subcoordinate_y'] is True


def test_subcoordinate_y_dict(load_pandas_accessor):
df = pd.DataFrame(np.random.random((10, 3)), columns=list('ABC'))
plot = df.hvplot.line(subcoordinate_y={'subcoordinate_scale': 2})
opts = Store.lookup_options('bokeh', plot, 'plot')
assert opts.kwargs['subcoordinate_y'] is True
assert opts.kwargs['subcoordinate_scale'] == 2
Loading