A quick chart reveals trends, outliers and distribution shapes that summary tables hide.
Every Series and DataFrame has a `.plot` accessor that draws with Matplotlib (which must be installed). It's built for fast exploratory charts with sensible defaults: the index becomes the x-axis and each column becomes a series.
Chart kinds via kind= or the accessor methods:
df.plot()/.plot.line(): trends over an ordered index such as dates.plot.bar()/.plot.barh(): compare categories, typically after a groupby.plot.hist(bins=30): distribution of one column;.plot.box()compares distributions.plot.scatter(x="a", y="b"): relationship between two columns (DataFrame only).plot.area(),.plot.pie()for the occasional special case
Most plotting is the last step of a chain: aggregate first, then plot. df.groupby("region")["sales"].sum().sort_values().plot.barh() is a complete chart. For a time series, set a DatetimeIndex, maybe resample, then plot.
Useful arguments: title=, figsize=(8, 4), logy=True, subplots=True (one panel per column), ax= to draw into an existing Matplotlib axes, and color=. Each call returns a Matplotlib Axes, so you can keep customising with the Matplotlib API: ax.set_ylabel("EUR"), ax.axhline(0), and save with ax.figure.savefig("chart.png", dpi=150).
In a script, call matplotlib.pyplot.show() to open a window; in Jupyter charts appear automatically.
pandas plotting is for exploration and simple reports. For publication styling or interactive charts, pass the tidy (long) data to Seaborn, Plotly or Altair. pandas can also switch its backend with pd.options.plotting.backend = "plotly" if that package is installed.
Example
import matplotlib
matplotlib.use("Agg") # headless: just write files
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
rng = np.random.default_rng(1)
days = pd.date_range("2024-01-01", periods=90, freq="D")
df = pd.DataFrame({"visits": rng.poisson(200, 90).cumsum(),
"region": rng.choice(["N", "S", "E"], 90),
"spend": rng.gamma(2, 20, 90)}, index=days)
ax = df["visits"].plot(title="Cumulative visits", figsize=(8, 3))
ax.set_ylabel("visits")
ax.figure.savefig("visits.png", dpi=120)
fig, (left, right) = plt.subplots(1, 2, figsize=(9, 3)) # new figure
df.groupby("region")["spend"].sum().sort_values().plot.barh(ax=left)
df["spend"].plot.hist(bins=20, alpha=0.7, ax=right, title="Spend")
fig.savefig("spend.png")
print(type(left).__name__) # AxesRemember
.ploton a Series/DataFrame draws with Matplotlib; the index is the x-axis- Aggregate first, then plot: groupby result plus
.plot.bar()is a full chart - Each call returns a Matplotlib Axes for further tweaks and
savefig - Use Seaborn, Plotly or Altair for polished or interactive charts
Watch out for
- Plotting unsorted, unaggregated raw rows as a line chart and getting a meaningless zigzag.
- Calling
.plotrepeatedly in a script withoutax=or a new figure, so charts are drawn on top of each other in the current axes.