Axis Options#

Customization options for axis appearance and behavior, including labels, limits, tick formatting, and axis scaling:

Parameters

Description

autorange (Literal[‘x’, ‘y’] or None, default=None)

Whether to enable auto-ranging along the x- or y-axis when zooming. Only supported by the Bokeh backend.

Added in version 0.9.0.

flip_xaxis/flip_yaxis (bool or None, default=None)

Whether to flip the axis left to right or up and down respectively.

framewise (bool, default=True)

Whether to compute the axis ranges frame-by-frame when using dynamic plots.

invert (bool, default=False)

Swaps x- and y-axis.

logx/logy (bool, default=False)

Enables logarithmic x- and y-axis respectively.

loglog (bool or None, default=None)

Enables logarithmic x- and y-axis.

rot (number or None, default=None)

Rotates the axis ticks along the x-axis by the specified number of degrees.

shared_axes (bool, default=True)

Whether to link axes between plots.

subcoordinate_y (bool or dict or None, default=None)

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}.

Added in version 0.11.0.

title (str or None, default=None)

Title for the plot.

xaxis (str or bool or None)

Whether to show the x-axis and whether to place it at the top or bottom. A bare axis means that an axis line is still displayed but there are no axis ticks and labels. Valid options include: bottom (default), bottom-bare, top, top-bare, None (no axis at all), True (same as bottom), and False (same as None).

yaxis (str or bool or None)

Whether to show the y-axis and whether to place it at the left or right. A bare axis means that an axis line is still displayed but there are no axis ticks and labels. Valid options include: left (default), left-bare, right, right-bare, None (no axis at all), True (same as left), and False (same as None).

xformatter/yformatter (str or bokeh.TickFormatter or None, default=None)

Formatter for the x-axis and y-axis (accepts printf formatter, e.g. ‘%.3f’, and bokeh TickFormatter).

xlabel/ylabel/clabel (str or None, default=None)

Axis labels for the x-axis, y-axis, and colorbar.

xlim/ylim (tuple or None, default=None)

Plot limits of the x- and y-axis. One bound can be left unset by using None (e.g. xlim=(10, None) means there is no upper bound).

xticks/yticks/cticks (int or list or np.ndarray or None, default=None)

Ticks along x-axis and y-axis, as an integer, list of ticks positions, Numpy ndarray, or list of tuples of the tick positions and labels. Also accepts a Bokeh Ticker instance when the Bokeh plotting backend is enabled.

Added in version 0.11.0: cticks was added in this version and is only supported by the Bokeh plotting backend.

autorange#

The autorange option allows enabling autoranging on the x or y axis. When enabled, the range of the selected axis is automatically computed and updated based on the data range in that axis. Setting autorange="y" is practical for inspecting closely long timeseries, as it zooming and panning actions will always end up focusing on the timeseries, which can be cumbersome without autoranging.

In the example below, zoom and pan the second plot to observe the effect of y-axis autoranging. Note that this feature does not require an interactive Python kernel.

import hvplot.pandas  # noqa

df = hvplot.sampledata.stocks("pandas").set_index("date")["Apple"]

df.hvplot.line(autorange=None, width=300, title="No y-axis autoranging") +\
df.hvplot.line(autorange="y", width=300, shared_axes=False, title="y-axis autoranging")

flip_xaxis / flip_yaxis#

These options allow to flip the x and y axis. The examples below show their effect, notice how the axes, when flipped, start with a value of about 2 which then decreases.

import hvplot.pandas  # noqa
import pandas as pd

df = pd.DataFrame({
    "x": list(range(3)), "y": list(range(3)),
    "v": ["a", "b", "c"], "s": list(range(100, 700, 200)),
})

plot_opts = dict(
    x="x", y="y", color="v", s="s", legend=False,
    aspect=1, frame_width=200, shared_axes=False,
)
(
    df.hvplot.scatter(flip_xaxis=False, flip_yaxis=False, title="None", **plot_opts) +
    df.hvplot.scatter(flip_xaxis=True, flip_yaxis=False, title="flip_xaxis", **plot_opts) +
    df.hvplot.scatter(flip_xaxis=False, flip_yaxis=True, title="flip_yaxis", **plot_opts) +
    df.hvplot.scatter(flip_xaxis=True, flip_yaxis=True, title="flip_xaxis + flip_yaxis", **plot_opts)
).cols(2)

framewise#

hvPlot can generate plots that are composed of multiple frames in an animation or controlled with widgets, for instance with the groupby option. The framewise option allows to control whether the axis ranges are computed frame-by-frame or instead normalized across all the frames. framewise is True by default, meaning the axis ranges are not normalized but computed frame-by-frame. Setting framewise to False is useful to directly compare the frames.

In the examples below update the widget value and observe the axis and colorbar ranges, you should see that they adapt to the data range with framewise=True (default) and stay constant with framewise=False.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(x="bill_length_mm", y="bill_depth_mm", groupby="island", frame_width=300, dynamic=False)
plot_default = df.hvplot.scatter(framewise=True, title="framewise=True (default)", **plot_opts)
plot_not_framewise = df.hvplot.scatter(framewise=False, title="framewise=False", **plot_opts)
plot_default
plot_not_framewise
import hvplot.xarray  # noqa

ds = hvplot.sampledata.air_temperature("xarray").isel(time=slice(0, 2))

plot_opts = dict(dynamic=False, frame_width=300)
plot_not_framewise = ds.hvplot.image(framewise=False, title="framewise=False", **plot_opts)
plot_default = ds.hvplot.image(title="framewise=True", **plot_opts)
plot_default
plot_not_framewise

See also

invert#

The invert option swaps the x- and y-axis.

import hvplot.pandas  # noqa
import pandas as pd

df = pd.DataFrame({"cat": ["A", "B", "C"], "value": [20, 10, 30]})

plot_opts = dict(x="cat", y="value", aspect=1, frame_width=200)
df.hvplot.bar(invert=False, title="invert=False (default)", **plot_opts) +\
df.hvplot.bar(invert=True, title="invert=True", **plot_opts)

logx / logy#

These options control whether the x and y axes are defined with a logarithmic scale.

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

df = pd.DataFrame({"x":(x:= np.logspace(0.1, 3, 20)), "y": x ** 2})

plot_opts = dict(x="x", y="y", aspect=1, frame_width=200, shared_axes=False)
df.hvplot.scatter(logx=True, title="logx=True", **plot_opts) +\
df.hvplot.scatter(logy=True, title="logy=True", **plot_opts)

loglog#

This controls whether both the x and y axes are defined with a logarithmic scale.

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

df = pd.DataFrame({"x":(x:= np.logspace(0.1, 3, 20)), "y": x ** 2})

plot_opts = dict(x="x", y="y", aspect=1, frame_width=200, shared_axes=False)
df.hvplot.scatter(loglog=True, title="loglog=True", **plot_opts)

rot#

The rot option rotates the x-axis ticks by the specified number of degrees (positive values only). It is useful to avoid the overlapping of long labels, as shown in the example below.

import hvplot.pandas  # noqa
import pandas as pd

df = pd.DataFrame({"name": ["Very Long Name 1", "Very Long Name 2"], "value": [10, 20]})

df.hvplot.bar(x="name", y="value", rot=45, width=150, height=300)
import hvplot.pandas  # noqa
import pandas as pd

df = pd.DataFrame({"name": ["Very Long Name 1", "Very Long Name 2"], "value": [10, 20]})

df.hvplot.bar(x="name", y="value", rot=45, invert=True, height=150, width=400)

shared_axes#

hvPlot automatically normalizes, and links (for the Bokeh plotting backend), the axes of plots in a layout that share the same variable/dimension name. This behavior can be disabled by setting shared_axes to False.

The first three examples below demonstrate the default (shared_axes=True) behavior of hvPlot. In this first example, the layout contains two plots that share different data values but the same variable names 'x' and 'y'. Panning and zooming the plot, you can see the axes are linked.

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

df1 = pd.DataFrame({"x": (x:= np.linspace(-2*np.pi, 2*np.pi, 50)), "y": np.sin(x)})
df2 = pd.DataFrame({"x": (x:= np.linspace(-5*np.pi, 5*np.pi, 50)), "y": 5*np.sin(x)})

(
    df1.hvplot.line(x="x", y="y", frame_width=200, aspect=1) +
    df2.hvplot.line(x="x", y="y", frame_width=200, aspect=1)
).opts(title="x and y axes shared")

In this example, only the y axis is linked as both plots just share the 'y' dimension.

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

df1 = pd.DataFrame({"x1": (x:= np.linspace(-2*np.pi, 2*np.pi, 50)), "y": np.sin(x)})
df2 = pd.DataFrame({"x2": (x:= np.linspace(-5*np.pi, 5*np.pi, 50)), "y": 5*np.sin(x)})

(
    df1.hvplot.line(x="x1", y="y", frame_width=200, aspect=1) +
    df2.hvplot.line(x="x2", y="y", frame_width=200, aspect=1)
).opts(title="y axes shared")

In this example, only the x axis is linked as both plots just share the 'x' dimension.

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

df1 = pd.DataFrame({"x": (x:= np.linspace(-2*np.pi, 2*np.pi, 50)), "y1": np.sin(x)})
df2 = pd.DataFrame({"x": (x:= np.linspace(-2*np.pi, 2*np.pi, 50)), "y2": 5*np.sin(x)})

(
    df1.hvplot.line(x="x", y="y1", frame_width=200, aspect=1) +
    df2.hvplot.line(x="x", y="y2", frame_width=200, aspect=1)
).opts(title="x axes shared")

In order to disable shared axes, we need to set shared_axed=False to at least the last plot in the layout.

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

df1 = pd.DataFrame({"x1": (x:= np.linspace(-2*np.pi, 2*np.pi, 50)), "y": np.sin(x)})
df2 = pd.DataFrame({"x2": (x:= np.linspace(-5*np.pi, 5*np.pi, 50)), "y": 5*np.sin(x)})

(
    df1.hvplot.line(x="x1", y="y", frame_width=200, aspect=1) +
    df2.hvplot.line(x="x2", y="y", frame_width=200, aspect=1, shared_axes=False)
).opts(title="y axes shared")

Axes are also shared by default for layouts created with the subplots option.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

df.hvplot.scatter(
    x="bill_length_mm", y="bill_depth_mm", by="sex",
    subplots=True, frame_width=200, aspect=1,
).opts(title="x and y axes shared")

This can be disabled with shared_axes=False.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

df.hvplot.scatter(
    x="bill_length_mm", y="bill_depth_mm", by="sex",
    subplots=True, frame_width=200, aspect=1, shared_axes=False,
).opts(title="x and y axes not shared")

subcoordinate_y#

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 option 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.

Use the wheel zoom on the plots below to zoom in all the time series simultaneously.

import hvplot.pandas  # noqa

df = hvplot.sampledata.stocks("pandas")
df.hvplot.line(subcoordinate_y=True, title="subcoordinate_y=True")
import hvplot.pandas  # noqa

df = hvplot.sampledata.stocks("pandas")

df.hvplot.line(subcoordinate_y={"subcoordinate_scale": 2}, title="50% overlapping subcoordinate_y")

title#

The title option allows to set the overall plot title.

Note

For simple plots, setting the plot title with title or with the label option both lead to a similar visual output. However, the HoloViews object returned will only have its label attribute set when the label option is used.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

df.hvplot.scatter("bill_depth_mm", "bill_length_mm", width=400, title="Plot title")

xaxis#

Control the x-axis location and display with xaxis.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(x="bill_depth_mm", y="bill_length_mm", frame_width=200, aspect=1)

(
    df.hvplot.scatter(xaxis="bottom", title="xaxis=bottom (default)", **plot_opts) +
    df.hvplot.scatter(xaxis="bottom-bare", title="xaxis=bottom-bare", **plot_opts) +
    df.hvplot.scatter(xaxis="top", title="xaxis=top", **plot_opts) +
    df.hvplot.scatter(xaxis="top-bare", title="xaxis=top-bare", **plot_opts) +
    df.hvplot.scatter(xaxis="bare", title="xaxis=bare", **plot_opts) +
    df.hvplot.scatter(xaxis=None, title="xaxis=None", **plot_opts) +
    df.hvplot.scatter(xaxis=True, title="xaxis=True", **plot_opts) +
    df.hvplot.scatter(xaxis=False, title="xaxis=False", **plot_opts)
).cols(2)

yaxis#

Control the y-axis location and display with yaxis.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(x="bill_depth_mm", y="bill_length_mm", frame_width=200, aspect=1)

(
    df.hvplot.scatter(yaxis="left", title="yaxis=left (default)", **plot_opts) +
    df.hvplot.scatter(yaxis="left-bare", title="yaxis=left-bare", **plot_opts) +
    df.hvplot.scatter(yaxis="right", title="yaxis=right", **plot_opts) +
    df.hvplot.scatter(yaxis="right-bare", title="yaxis=right-bare", **plot_opts) +
    df.hvplot.scatter(yaxis="bare", title="yaxis=bare", **plot_opts) +
    df.hvplot.scatter(yaxis=None, title="yaxis=None", **plot_opts) +
    df.hvplot.scatter(yaxis=True, title="yaxis=True", **plot_opts) +
    df.hvplot.scatter(yaxis=False, title="yaxis=False", **plot_opts)
).cols(2)

xformatter / yformatter#

These options allow to format the x and y tick labels. They accept a str object, or a Bokeh or Matplotlib formatter instance (depending on the active plotting backend).

When set to a str object, these formatters are:

  • Bokeh: PrintfTickFormatter (printf/old-style format string as used with the % operator); note that Bokeh computes the labels in the front-end using the JavaScript library sprintf.js, so the implementation can slightly differ from Python’s printf/old-style format string.

  • Matplotlib: StrMethodFormatter (new-style format string as used by str.format) if the string contains a reference to the format variable (available keys are x and pos, e.g. '{x} {pos}'), FormatStrFormatter (printf/old-style format string as used with the % operator) otherwise.

Bokeh’s PrintfTickFormatter can be useful for simple number formatting and other simple cases, you can find its specification below. Matplotlib’s StrMethodFormatter offers all the power of Python’s str.format.

Bokeh PrintfTickFormatter specification

The number format, as defined as follows:

The placeholders in the format string are marked by % and are followed by one or more of these elements, in this order:

  • An optional number followed by a $ sign that selects which argument index to use for the value. If not specified, arguments will be placed in the same order as the placeholders in the input string.

  • An optional + sign that forces to precede the result with a plus or minus sign on numeric values. By default, only the - sign is used on negative numbers.

  • An optional padding specifier that says what character to use for padding (if specified). Possible values are 0 or any other character preceded by a ' (single quote). The default is to pad with spaces.

  • An optional - sign, that causes sprintf to left-align the result of this placeholder. The default is to right-align the result.

  • An optional number, that says how many characters the result should have. If the value to be returned is shorter than this number, the result will be padded. When used with the j (JSON) type specifier, the padding length specifies the tab size used for indentation.

  • An optional precision modifier, consisting of a . (dot) followed by a number, that says how many digits should be displayed for floating point numbers. When used with the g type specifier, it specifies the number of significant digits. When used on a string, it causes the result to be truncated.

  • A type specifier that can be any of:

    • % — yields a literal % character

    • b — yields an integer as a binary number

    • c — yields an integer as the character with that ASCII value

    • d or i — yields an integer as a signed decimal number

    • e — yields a float using scientific notation

    • u — yields an integer as an unsigned decimal number

    • f — yields a float as is; see notes on precision above

    • g — yields a float as is; see notes on precision above

    • o — yields an integer as an octal number

    • s — yields a string as is

    • t — yields true or false

    • T — yields the type of the argument1

    • v — yields the primitive value of the specified argument

    • x — yields an integer as a hexadecimal number (lower-case)

    • X — yields an integer as a hexadecimal number (upper-case)

    • j — yields a JavaScript object or array as a JSON encoded string

For Bokeh plots, NumeralTickFormatter is a much more appropriate formatter for a wider range of number format options. You can find its complete specification below (Bokeh’s implementation leverages the JavaScript library numbro, visit their format reference for more information):

Bokeh NumericalTickFormatter specification

NUMBERS

Number

Format

String

10000

'0,0.0000'

10,000.0000

10000.23

'0,0'

10,000

10000.23

'+0,0'

+10,000

-10000

'0,0.0'

-10,000.0

10000.1234

'0.000'

10000.123

10000.1234

'0[.]00000'

10000.12340

-10000

'(0,0.0000)'

(10,000.0000)

-0.23

'.00'

-.23

-0.23

'(.00)'

(.23)

0.23

'0.00000'

0.23000

0.23

'0.0[0000]'

0.23

1230974

'0.0a'

1.2m

1460

'0 a'

1 k

-104000

'0a'

-104k

1

'0o'

1st

52

'0o'

52nd

23

'0o'

23rd

100

'0o'

100th

CURRENCY

Number

Format

String

1000.234

'$0,0.00'

$1,000.23

1000.2

'0,0[.]00 $'

1,000.20 $

1001

'$ 0,0[.]00'

$ 1,001

-1000.234

'($0,0)'

($1,000)

-1000.234

'$0.00'

-$1000.23

1230974

'($ 0.00 a)'

$ 1.23 m

BYTES

Number

Format

String

100

'0b'

100B

2048

'0 b'

2 KB

7884486213

'0.0b'

7.3GB

3467479682787

'0.000 b'

3.154 TB

PERCENTAGES

Number

Format

String

1

'0%'

100%

0.974878234

'0.000%'

97.488%

-0.43

'0 %'

-43 %

0.43

'(0.000 %)'

43.000 %

TIME

Number

Format

String

25

'00:00:00'

0:00:25

238

'00:00:00'

0:03:58

63846

'00:00:00'

17:44:06

This table contains a subset of common number formats that can be set with NumeralTickFormatter:

Format

Example Input

Output

Use Case

'0,0'

12345.67

12,346

General whole numbers

'0.0a'

1230000

1.2m

Large numbers (compact form)

'0%'

0.45

45%

Percent values

'0.0'

123.456

123.5

One decimal place

'0.00'

123.456

123.46

Two decimal places

'$0,0'

12345

$12,345

Financial (whole dollar)

'$0,0.00'

12345.67

$12,345.67

Financial (cents included)

'0.00e+0'

0.0000123

1.23e-5

Scientific notation (2 decimals)

'0e+0'

123000000

1e+8

Scientific notation (rounded)

For datetime formatting:

Visit this page from Bokeh’s user guide to more explanation about Bokeh’s formatters.

Bokeh#

This example sets a simple printf style y-formatter and a custom DatetimeTickFormatter x-formatter that sets the date format when in the days range and a context (find more information on datetime tick context in Bokeh’s documentation).

import hvplot.pandas  # noqa

from bokeh.models import DatetimeTickFormatter, RELATIVE_DATETIME_CONTEXT

df = hvplot.sampledata.apple_stocks("pandas").set_index("date").loc["2023-01"]
df.hvplot.line(
    y="open", width=500,
    xformatter=DatetimeTickFormatter(days="%B %d", context=RELATIVE_DATETIME_CONTEXT()),
    yformatter="$%.2f",
)

This example sets a NumeralTickFormatter y-formatter to format the volume in a more consice way.

import hvplot.pandas  # noqa

from bokeh.models import NumeralTickFormatter

df = hvplot.sampledata.apple_stocks("pandas").set_index("date").loc["2023-01"]
df.hvplot.line(y="volume", width=500, yformatter=NumeralTickFormatter(format="0.0a"))

Matplotlib#

These two examples set a DateFormatter x-formatter, and an printf and a str.format y-formatters, respectively.

import hvplot.pandas  # noqa
import matplotlib as mpl
hvplot.extension("matplotlib")

df = hvplot.sampledata.apple_stocks("pandas").set_index("date").loc["2023-01"]

df.hvplot.line(y="open", xformatter=mpl.dates.DateFormatter("%Y-%m-%d"), yformatter="$%.2f")
import hvplot.pandas  # noqa
hvplot.extension("matplotlib")

df = hvplot.sampledata.apple_stocks("pandas").set_index("date").loc["2023-01"]

df.hvplot.line(y="open", xformatter=mpl.dates.DateFormatter("%Y-%m-%d"), yformatter="${x:.2f} | pos={pos}")

xlabel / ylabel / clabel#

These options are useful for overwriting the default label values, which are by default automatically set from the variable names.

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

df.hvplot.scatter(
    x="bill_depth_mm", y="bill_length_mm", color="body_mass_g", width=400,
    xlabel="Bill depth [mm]", ylabel="Bill length [mm]", clabel="Body mass [g]"
)

xlim / ylim#

The x- and y-axis ranges can be defined with the xlim and ylim options, respectively. These options accept a 2-tuple representing the minimum and maximum bounds of the plotted ranged. One bound can be left unset by using None (e.g. xlim=(10, None) means there is no upper bound).

import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(x="bill_depth_mm", y="bill_length_mm", height=200, width=200, shared_axes=False)
(
    df.hvplot.scatter(xlim=(18, None), title="xlim=(18, None)", **plot_opts) +
    df.hvplot.scatter(xlim=(None, 18), title="xlim=(None, 18)", **plot_opts) +
    df.hvplot.scatter(xlim=(16, 20), title="xlim=(16, 20)", **plot_opts) +
    df.hvplot.scatter(ylim=(45, None), title="ylim=(45, None)", **plot_opts) +
    df.hvplot.scatter(ylim=(None, 45), title="ylim=(None, 45)", **plot_opts) +
    df.hvplot.scatter(ylim=(40, 50), title="ylim=(40, 50)", **plot_opts)
).cols(3)

For datetime axes, the bounds are expected to be in a datetime value like a pandas.Timestamp object.

import hvplot.pandas  # noqa
import pandas as pd

df = hvplot.sampledata.stocks("pandas").set_index("date")

df.hvplot.line(width=500, xlim=(pd.Timestamp("2021"), pd.Timestamp("2023")))

xticks / yticks / cticks#

xticks yticks allow to control the number and/or location of the x- and y-axis ticks. cticks has the same effect on the colorbar axis.

import hvplot.pandas  # noqa
import numpy as np

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(x="bill_depth_mm", y="bill_length_mm", frame_width=200, aspect=1, fontsize={"title": "10pt"})
(
    df.hvplot.scatter(xticks=None, title="xticks=None (default)", **plot_opts) +
    df.hvplot.scatter(xticks=2, title="xticks=2", **plot_opts) +
    df.hvplot.scatter(xticks=[15, 17.5, 20], title="xticks=[15, 17.5, 20]", **plot_opts) +
    df.hvplot.scatter(xticks=np.arange(10, 25, 1), title="xticks=np.arange(10, 25, 1)", **plot_opts) +
    df.hvplot.scatter(xticks=[(15, "small"), (20, "big")], title='xticks=[(15, "small"), (20, "big")]', **plot_opts) +
    df.hvplot.scatter(xaxis=None, yaxis=None, c="white", **plot_opts) +
    df.hvplot.scatter(yticks=None, title="yticks=None (default)", **plot_opts) +
    df.hvplot.scatter(yticks=2, title="yticks=2", **plot_opts) +
    df.hvplot.scatter(yticks=[35, 45, 55], title="yticks=[35, 45, 55]", **plot_opts) +
    df.hvplot.scatter(yticks=np.arange(30, 65, 5), title="yticks=np.arange(30, 65, 5)", **plot_opts) +
    df.hvplot.scatter(yticks=[(35, "small"), (55, "big")], title='yticks=[(35, "small"), (55, "big")]', **plot_opts) +
    df.hvplot.scatter(xaxis=None, yaxis=None, c="white", **plot_opts)
).cols(2)
import hvplot.pandas  # noqa
import pandas as pd

df = hvplot.sampledata.stocks("pandas").set_index("date")

df.hvplot.line(width=500, xticks=pd.date_range("2019", "2024", freq="6ME").to_list(), rot=45)

When creating a Bokeh plot, xaxis and yaxis also accept a custom Bokeh ticker object.

import bokeh as bk
import hvplot.pandas  # noqa

df = hvplot.sampledata.stocks("pandas").set_index("date").loc["2023-01"]
df.hvplot.line(
    width=500,
    xticks=bk.models.DaysTicker(days=list(range(1, 32, 7))),
    yticks=bk.models.SingleIntervalTicker(interval=1),
)

cticks accept a similar set of values.

import bokeh
import hvplot.pandas  # noqa

df = hvplot.sampledata.penguins("pandas")

plot_opts = dict(
    x="bill_depth_mm", y="bill_length_mm", color="body_mass_g",
    frame_width=200, aspect=1, fontsize={"title": "10pt"}
)
(
    df.hvplot.scatter(cticks=None, title="cticks=None (default)", **plot_opts) +
    df.hvplot.scatter(cticks=2, title="cticks=2", **plot_opts) +
    df.hvplot.scatter(cticks=[3000, 4500, 6000], title="cticks=[3000, 4500, 6000]", **plot_opts) +
    df.hvplot.scatter(cticks=np.arange(3000, 6500, 500), title="cticks=np.arange(3000, 6500, 500)", **plot_opts) +
    df.hvplot.scatter(cticks=[(3000, "small"), (6000, "big")], title='cticks=[(3000, "small"), (6000, "big")]', **plot_opts) +
    df.hvplot.scatter(cticks=bokeh.models.SingleIntervalTicker(interval=1000), title='cticks=bokeh.models.Ticker()', **plot_opts)
).cols(2)
This web page was generated from a Jupyter notebook and not all interactivity will work on this website.