Skillversitas

Customizing Axes and Ticks

The Axes frame - limits, ticks, labels, spines, grid - is where a chart goes from default to deliberate. The defaults (auto-limits, five ticks, black frame on all four sides) are reasonable for exploration and wrong for publication: publication charts usually trim the top and right spines, control the tick set explicitly, and add a quiet grid. This chapter is the toolbox for all of it.

Axis Limits

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x) + x / 5)

ax.set_xlim(0, 8)                 # zoom in horizontally
ax.set_ylim(-0.2, 1.6)            # fixed vertical window
ax.invert_yaxis()                 # y grows downward (maps, depth)
plt.show()

Auto-scaling picks "nice" limits around the data; set_xlim/set_ylim override it. Set limits before adding data only if you know the range - otherwise let the first data call establish the frame and then adjust. margins(0.05) adds padding instead of replacing the limits.

Ticks: Values and Labels

import matplotlib.pyplot as plt

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
values = [12, 15, 9, 18, 14, 21]

fig, ax = plt.subplots()
ax.plot(range(len(months)), values, marker="o")
ax.set_xticks(range(len(months)))
ax.set_xticklabels(months)
ax.set_yticks([0, 5, 10, 15, 20])
ax.tick_params(axis="both", which="major", labelsize=10, length=4)
plt.show()

set_xticks places ticks; set_xticklabels renames them (same count, or use a dict-style formatter). tick_params styles length, width, color, and label size for the major and minor tick sets at once. For large numbers, a formatter is cleaner than manual labels:

from matplotlib.ticker import FuncFormatter, MultipleLocator

ax.yaxis.set_major_formatter(FuncFormatter(lambda v, _: f"{v:,.0f}"))
ax.xaxis.set_major_locator(MultipleLocator(5))   # a tick every 5 units

Spines

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([0, 1, 2], [1, 4, 2])

ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_color("gray")
ax.spines["bottom"].set_color("gray")
plt.show()

Each side of the frame is a Spine artist addressable by name. Hiding the top and right is the standard "clean" style - it removes the box around the data without losing the reference edges. Move the left spine to x=0 with ax.spines["left"].set_position("zero") for zero-referenced charts.

Grids

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot([0, 1, 2, 3], [2, 5, 3, 7])

ax.grid(True, which="both", axis="y",
        linestyle=":", linewidth=0.6, alpha=0.6)
plt.show()

Grid options: which="major"/"minor"/"both", axis="x"/"y"/"both", plus any line style. Horizontal-only grids (for time series) are the most useful form; keep them light - the data should be the loudest thing on the page.

Nonlinear Scales

  • ax.set_xscale("log") - orders of magnitude (revenue growth, file sizes); data must be positive.
  • ax.set_yscale("symlog", linthresh=1) - log behavior with a linear zone around zero.
  • ax.set_aspect("equal") - one unit on x equals one unit on y (geometry, physics plots).
  • ax.set_proj / transforms - for the unusual cases, covered with annotations.

Summary

Take control of the frame: fix limits where the data range misleads, set explicit ticks with formatters for readability, hide the top and right spines for the clean style, add a quiet major grid, and switch to log scales when the data spans orders of magnitude. Every one of these is a one-line Axes method - the defaults exist so you can start; these exist so you can finish.