GadaaLabs
Python Mastery — From Zero to AI Engineering
Lesson 11

Data Visualization — Matplotlib, Seaborn & Interactive Charts

26 min

Matplotlib Architecture: Understanding the Object Model

Matplotlib has two APIs and most tutorials mix them up, creating confusion. Understanding the underlying architecture makes both APIs clear.

Every matplotlib plot is a hierarchy of Artist objects:

Figure              — the entire window/canvas
└── Axes            — one plot region (has an x and y axis)
    ├── Axis        — the x-axis or y-axis object (ticks, labels, limits)
    ├── Line2D      — a line plot
    ├── PathPatch   — a bar or polygon
    ├── Text        — any text element
    └── ...

pyplot (plt.*) is a state-machine interface that tracks the "current figure" and "current axes" implicitly. It's convenient for interactive work but dangerous in scripts — functions operate on whichever Axes was last created, which can cause subtle bugs.

The object-oriented API (fig, ax = plt.subplots()) gives you explicit handles. Always use it in production code.

Python
Click Run to execute — Python runs in your browser via WebAssembly

Line Plots, Scatter Plots & Styling

Python
Click Run to execute — Python runs in your browser via WebAssembly

Subplots, GridSpec & Annotations

Python
Click Run to execute — Python runs in your browser via WebAssembly

Seaborn: Statistical Visualization

Seaborn is built on top of matplotlib and provides higher-level functions for statistical graphics. It integrates natively with pandas DataFrames.

Python
Click Run to execute — Python runs in your browser via WebAssembly

Tick Formatting, Styling & Saving

Python
Click Run to execute — Python runs in your browser via WebAssembly

PROJECT: Exploratory Data Analysis Dashboard

Python
Click Run to execute — Python runs in your browser via WebAssembly

PROJECT: Time Series — Stock Price with Moving Averages

Python
Click Run to execute — Python runs in your browser via WebAssembly

Key Takeaways

  • Always use the OO API for scripts: fig, ax = plt.subplots() gives explicit handles and is immune to the "current axes" state bugs that plague plt.* code
  • fig.tight_layout() and fig.savefig(bbox_inches='tight'): these two calls fix 90% of "labels are cut off" problems — make them habits
  • ax.set_* methods do everything: set_title, set_xlabel, set_xlim, set_yscale('log'), set_aspect('equal') — prefer these over the plt.* equivalents which may act on the wrong Axes
  • Annotations require xy (data point) and xytext (label position): always specify both; arrowprops controls the connector style between them
  • GridSpec enables complex multi-panel figures: use gridspec_kw={"height_ratios":[3,1]} in plt.subplots() for simple cases, or gridspec.GridSpec for full control
  • Seaborn's set_theme changes matplotlib's global defaults: call it once at the top — it affects all subsequent plots including plain matplotlib ones
  • plt.show() triggers rendering in the playground: the component captures the figure at this call; without it, nothing renders
  • Color consistency tells a story: assign colors to categories once (e.g., a palette dict) and reuse across all panels — inconsistent colors confuse readers even when other design is perfect