hvplot icon indicating copy to clipboard operation
hvplot copied to clipboard

xticks/yticks argument does not work for hvplot heatmap

Open nicolejkeeney opened this issue 3 years ago • 2 comments

Short description of issue

I really need to reduce the density of yticks on my heatmap. Supposedly, the xticks and yticks argument should be able to do this, but it doesn't work, and actually makes my plot disappear.

Software version info

hvplot version: 0.8.0 pandas version: 1.3.4

Complete, minimal, self-contained example code that reproduces the issue

Code is pasted below. A Jupyter Notebook with this code and data used by the notebook is also included.
Zip file with data and notebook: data_and_notebook.zip

Code snippet from notebook:

df = pd.read_csv("tmy_data.csv", index_col="date") # Read data 

heatmap2 = df.hvplot.heatmap( # Make plot
    x="columns",
    y="index",
    rot=60,
    width=800,
    height=350,
    yticks=12
)
heatmap2

Screenshots or screencasts of the bug in action

notebook output

Description of expected behavior and the observed behavior

Expected Behavior: yticks argument reduces the number of yticks present if I feed it an integer value (i.e. if i set yticks=10, I should get back a heatmap with 10 yticks). Observed behavior: No heatmap is returned

nicolejkeeney avatar Nov 21 '22 23:11 nicolejkeeney

Hi @nicolejkeeney !

Thanks for reporting this issue. I believe hvPlot doesn't handle two things properly there:

  • in general it struggles with categorical axes, which is the case in your data
  • when it struggles, it should say so by emitting a warning or raising an error with an informative message

Two workarounds that might be worth trying in the mean time:

  • in the reference gallery you'll see that your data can be a long timeseries and use Pandas datetime features (e.g. df.hvplot.heatmap(x='time.month', y='time.day')). This is also demonstrated in the timeseries data guide. Using that approach, the yticks option works as expected.
  • the yticks option work well on numerical data so you could replace your index by the default Pandas index (0, 1, 2, etc.) and set yticks as a list of (index, label), every X label being the original labels while the others are set to empty strings.

maximlt avatar Dec 05 '22 11:12 maximlt

Same (or very similar) thing happens for me with grouped box and violin plots.

mport hvplot
import hvplot.xarray
import xarray as xr
import numpy as np
from bokeh.models import BasicTickFormatter

if __name__ == "__main__":
    # make a dummy xarray dataset with two dimensions
    dim1_size = 10000
    dim2_size = 50
    xds = xr.Dataset(
        {"values": (("dim1", "dim2"), np.random.random((dim1_size, dim2_size)))},
        coords={"dim1": np.arange(dim1_size), "dim2": np.arange(dim2_size)},
    )

    # this works, but the horizontal axis labels overrun and are illegible
    p = xds.hvplot.violin("values", by="dim2")
    hvplot.show(p)

    # --------------------------------------------------
    # for each of the following, a server starts and no plot appears at all

    # p = xds.hvplot.violin("values", by="dim2", xticks=[0, 25, 50])
    # hvplot.show(p)

    # p = xds.hvplot.violin("values", by="dim2").opts(xticks=[1, 25, 50])
    # hvplot.show(p)

    # formatter = BasicTickFormatter()
    # p = xds.hvplot.violin("values", by="dim2").opts(xformatter=formatter)
    # hvplot.show(p)

Timothy-W-Hilton avatar May 11 '23 01:05 Timothy-W-Hilton

just noting this is still happening in v11.1. The suggested workaround of using time series features doesn't really help.

import hvplot
import hvplot.xarray
import matplotlib.ticker
import numpy as np
import pandas as pd
import xarray as xr
from bokeh.models import BasicTickFormatter

DAYS_IN_YEAR = 365

if __name__ == "__main__":
    # make a dummy xarray dataset with two dimensions
    dim1_size = 10000
    dim2_size = DAYS_IN_YEAR
    xds = xr.Dataset(
        {"values": (("dim1", "dim2"), np.random.random((dim1_size, dim2_size)))},
        coords={"dim1": np.arange(dim1_size), "dim2": np.arange(dim2_size)},
    )
    xds = xds.assign_coords(date=('dim2', pd.to_timedelta(range(DAYS_IN_YEAR), unit="d") + pd.to_datetime("2016/1/1")))

    # this works, but the horizontal axis labels overrun and are illegible
    p1 = xds.hvplot.violin("values", by="dim2")

    # the suggested workaround of using timeseries features does not help:
    p2 = xds.hvplot.violin("values", by="date.dayofyear")
    hvplot.show(p1 + p2)

Image

Timothy-W-Hilton avatar Dec 15 '24 23:12 Timothy-W-Hilton