// complete reference guide
Matplotlib & Seaborn
Graph Types
Every chart type across both libraries — with use cases, syntax, and applications. Sourced from official documentation and organized by category.
Pairwise & Basic Data
7 chartsConnects data points with lines. The most fundamental chart for displaying trends, time series, or functional relationships between two continuous variables.
import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10, 100) y = np.sin(x) plt.plot(x, y, color='steelblue', linewidth=2, label='sin(x)') plt.xlabel('X'); plt.ylabel('Y') plt.title('Line Plot'); plt.legend(); plt.show()
Plots individual data points as markers. Ideal for revealing correlations, clusters, and outliers between two continuous variables without connecting them.
x = np.random.randn(100) y = 2*x + np.random.randn(100) colors = np.abs(x) # color by value plt.scatter(x, y, c=colors, cmap='viridis', s=60, alpha=0.7) plt.colorbar(label='Intensity') plt.title('Scatter Plot'); plt.show()
Rectangular bars of height proportional to values. Perfect for comparing discrete categories or groups side-by-side. Use plt.barh() for horizontal bars.
categories = ['Q1', 'Q2', 'Q3', 'Q4'] values = [42, 58, 73, 91] plt.bar(categories, values, color='#ff6b35', edgecolor='white', linewidth=0.5) plt.title('Quarterly Sales'); plt.show() # Horizontal: plt.barh(categories, values)
Draws vertical lines (stems) from baseline to data points topped with markers. Excellent for discrete signal and digital data visualization where individual samples matter.
n = np.arange(0, 20) y = np.cos(n * 0.4) * np.exp(-n * 0.1) plt.stem(n, y, linefmt='steelblue', markerfmt='o', basefmt='gray') plt.title('Discrete Signal (Stem)'); plt.show()
Fills the area between two curves or between a curve and a baseline. Great for confidence intervals, uncertainty bands, and range highlighting.
x = np.linspace(0, 10, 200) y1 = np.sin(x) + 0.5 # upper bound y2 = np.sin(x) - 0.5 # lower bound plt.fill_between(x, y1, y2, alpha=0.3, color='royalblue', label='95% CI') plt.plot(x, np.sin(x), color='royalblue') plt.legend(); plt.show()
Stacked area chart where multiple series are stacked on top of each other. Shows both individual contributions and the total over a continuous domain.
x = [2020, 2021, 2022, 2023] y1 = [30, 35, 40, 50] # Product A y2 = [20, 25, 30, 28] # Product B y3 = [10, 15, 12, 18] # Product C plt.stackplot(x, y1, y2, y3, labels=['A','B','C'], alpha=0.8) plt.legend(loc='upper left'); plt.show()
Draws a step function connecting constant value segments. Useful for histograms without bars, cumulative distributions, and event-driven processes where values change in discrete steps.
vals = [1, 3, 2, 5, 4, 6] edges = np.arange(7) # bin edges plt.stairs(vals, edges, fill=True, color='teal', alpha=0.5) plt.title('Staircase Plot'); plt.show()
Statistical Distributions
9 chartsDivides data into bins and plots frequency counts as bars. The go-to tool for visualizing a variable's distribution, identifying skewness, peaks, and spread.
data = np.random.normal(0, 1, 1000) plt.hist(data, bins=30, color='steelblue', edgecolor='white', density=True) plt.xlabel('Value'); plt.ylabel('Density') plt.title('Histogram'); plt.show()
Summarizes distribution using five statistics: minimum, Q1, median, Q3, maximum. Box whiskers show spread; dots mark outliers. Perfect for comparing distributions across groups.
data = [np.random.normal(i, 1, 100) for i in [0, 2, 4]] fig, ax = plt.subplots() ax.boxplot(data, labels=['A','B','C'], patch_artist=True, boxprops=dict(facecolor='lightblue')) plt.show()
Plots points with error bars indicating uncertainty or variability. Essential for scientific data where measurement precision or confidence intervals must be communicated.
x = np.arange(1, 6) y = [2.3, 3.1, 4.8, 3.5, 5.2] yerr = [0.4, 0.3, 0.6, 0.5, 0.2] plt.errorbar(x, y, yerr=yerr, fmt='o-', capsize=5, color='royalblue', ecolor='gray', elinewidth=2) plt.title('Error Bar Plot'); plt.show()
Combines KDE density estimation with a box plot. The symmetric violin shape shows the full probability distribution, revealing bimodality and detailed distributional structure.
data = [np.random.normal(m, 0.8, 200) for m in [0, 2, 4, 6]] fig, ax = plt.subplots() vp = ax.violinplot(data, showmeans=True) for body in vp['bodies']: body.set_alpha(0.7) plt.show()
Displays collections of events as parallel vertical lines (like a raster plot). Standard in neuroscience for visualizing spike trains and in physics for particle events.
# Simulate 4 neurons spiking spikes = [np.sort(np.random.uniform(0, 1, 50)) for _ in range(4)] plt.eventplot(spikes, orientation='horizontal', colors=['r','g','b','orange'], linewidths=1.5) plt.title('Raster Plot'); plt.show()
A 2D histogram that divides the x-y plane into rectangular bins and color-codes the count in each. Better than scatter for very large datasets with overplotting issues.
x = np.random.normal(0, 1, 10000) y = np.random.normal(0, 1, 10000) plt.hist2d(x, y, bins=50, cmap='plasma') plt.colorbar(label='Count') plt.title('2D Histogram'); plt.show()
Aggregates scatter data into hexagonal bins, color-coding each by count or custom aggregation. Hexagons tile without gaps and are perceptually less biased than squares for spatial data.
x = np.random.randn(50000) y = np.random.randn(50000) hb = plt.hexbin(x, y, gridsize=30, cmap='inferno') plt.colorbar(hb, label='Count') plt.title('Hexbin Plot'); plt.show()
Circular chart divided into slices proportional to values. Best for showing part-to-whole relationships with a small number of categories (≤ 6). Use sparingly; bar charts are often clearer.
sizes = [35, 25, 20, 15, 5] labels = ['Python','JS','Java','C++','Other'] explode = [0.05]*5 plt.pie(sizes, labels=labels, explode=explode, autopct='%1.1f%%', startangle=90) plt.title('Language Popularity'); plt.show()
Empirical Cumulative Distribution Function. Shows the proportion of data below any given value without binning assumptions. Useful for comparing two distributions directly.
data = np.random.normal(0, 1, 500) # Available since matplotlib 3.8+ plt.ecdf(data, label='Group A') plt.xlabel('Value') plt.ylabel('Cumulative Probability') plt.legend(); plt.show()
Gridded Data
7 chartsDisplays matrix or image data as a colored pixel grid. The primary function for showing images, correlation matrices, confusion matrices, and any 2D array data.
Z = np.random.rand(10, 10) plt.imshow(Z, cmap='viridis', interpolation='nearest') plt.colorbar(); plt.title('imshow'); plt.show()
Creates a pseudocolor plot of a 2D array on a non-uniform grid. Like imshow but works on arbitrary (possibly non-rectangular) coordinate grids. Preferred over pcolor for performance.
X, Y = np.meshgrid(np.linspace(-3,3,50), np.linspace(-3,3,50)) Z = np.sin(X) * np.cos(Y) plt.pcolormesh(X, Y, Z, cmap='RdBu_r', shading='auto') plt.colorbar(); plt.show()
Draws iso-value contour lines on a 2D scalar field. Classic for topographic maps, pressure isobars in meteorology, and level sets in optimization landscapes.
X, Y = np.meshgrid(np.linspace(-2,2,100), np.linspace(-2,2,100)) Z = X**2 + Y**2 cs = plt.contour(X, Y, Z, levels=10) plt.clabel(cs, inline=True); plt.show()
Filled contour plot — same as contour but with solid color fills between levels. Ideal for showing continuous field strength visually; widely used in climate and fluid simulations.
Z = np.sin(X) + np.cos(Y) plt.contourf(X, Y, Z, levels=20, cmap='coolwarm') plt.colorbar(label='Amplitude') plt.title('Filled Contour'); plt.show()
Draws arrows on a grid to represent a 2D vector field. Direction and optionally magnitude are encoded. Used in fluid dynamics, electromagnetics, and gradient visualization.
X, Y = np.meshgrid(np.arange(-2,3), np.arange(-2,3)) U = -Y; V = X # circular field plt.quiver(X, Y, U, V, color='teal') plt.title('Quiver Plot'); plt.show()
Draws continuous streamlines following a 2D vector field. Unlike quiver, streamlines show flow paths rather than local arrows, making global flow patterns more legible.
Y, X = np.mgrid[-3:3:100j, -3:3:100j] U = -1 - X**2 + Y V = 1 + X - Y**2 speed = np.sqrt(U*U + V*V) plt.streamplot(X, Y, U, V, color=speed, cmap='autumn'); plt.show()
Meteorological wind barb symbols that encode both wind direction and speed using a flag-and-feather notation. Standard in weather maps and atmospheric science.
X, Y = np.meshgrid(np.arange(0,5), np.arange(0,5)) U = np.random.uniform(-20,20,X.shape) V = np.random.uniform(-20,20,Y.shape) plt.barbs(X, Y, U, V) plt.title('Wind Barbs'); plt.show()
Irregularly Gridded Data
4 chartsContour plot on unstructured triangular mesh data. Used when data comes from irregular sampling (sensors, FEM simulations) rather than a regular grid.
n = 200 x = np.random.uniform(-1, 1, n) y = np.random.uniform(-1, 1, n) z = x**2 - y**2 plt.tricontour(x, y, z, levels=8) plt.show()
Filled contour version of tricontour. Produces smooth filled regions on triangulated irregular networks, ideal for environmental data interpolation and geospatial analysis.
plt.tricontourf(x, y, z, levels=10, cmap='terrain') plt.colorbar(); plt.show()
Colors each triangle face by its value in a Delaunay triangulation. Shows raw unsmoothed triangulated data, useful for finite element visualization and debugging mesh quality.
plt.tripcolor(x, y, z, cmap='plasma') plt.colorbar(); plt.title('Tripcolor') plt.show()
Plots the Delaunay triangulation mesh over scatter data. Used to inspect mesh quality, verify triangulation of sensor placement, and as an overlay with tripcolor/tricontour.
plt.triplot(x, y, 'go-', linewidth=0.5, markersize=3) plt.title('Triangulation Mesh'); plt.show()
3D & Volumetric Data
10 chartsRenders a 3D surface mesh colored by height or custom values. The most popular 3D chart for mathematical functions, terrain models, and machine learning loss landscapes.
from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(); ax = fig.add_subplot(111, projection='3d') X, Y = np.meshgrid(np.linspace(-3,3,50), np.linspace(-3,3,50)) Z = np.sin(np.sqrt(X**2+Y**2)) ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.9) plt.show()
Renders a 3D surface as a mesh of lines (wireframe) without filled faces. Shows topology more clearly than solid surface for complex shapes; useful for demonstrating structure.
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2, color='steelblue', linewidth=0.5) plt.show()
3D scatter plot for three-variable relationships. Color and size can encode additional dimensions. Used in multivariate EDA, 3D clustering, and dimensionality reduction visualization.
xs = np.random.randn(200) ys = np.random.randn(200) zs = xs**2 + ys**2 ax.scatter(xs, ys, zs, c=zs, cmap='plasma', s=30, alpha=0.7) plt.show()
3D line plot — connects points in 3D space. Perfect for trajectories, parametric curves, time-evolving paths, and 3D signal traces like helices or Lissajous figures.
t = np.linspace(0, 4*np.pi, 300) xs = np.cos(t); ys = np.sin(t); zs = t ax.plot(xs, ys, zs, color='royalblue', lw=2) ax.set_title('3D Helix'); plt.show()
3D bar chart placing rectangular columns at (x,y) with heights dz. Useful for multi-categorical data and for adding a visually striking 3D dimension to standard bar comparisons.
xpos = [1,2,3]; ypos = [1,2,3] zpos = np.zeros(9) dx = dy = 0.6 dz = np.random.randint(1,10,9) ax.bar3d(np.repeat(xpos,3), np.tile(ypos,3), zpos, dx, dy, dz, shade=True)
Surface plot over irregular (not grid) 3D point data using Delaunay triangulation. Useful when z values come from scattered measurements rather than a regular XY grid.
theta = np.linspace(0, 2*np.pi, 200) r = np.random.uniform(0.1,1,200) x = r*np.cos(theta); y = r*np.sin(theta) z = x**2 + y**2 ax.plot_trisurf(x, y, z, cmap='coolwarm')
Renders 3D volumetric data as filled cubes (voxels). Used for 3D medical imaging, MRI data, CT scans, and any volumetric dataset with binary or categorical values.
x, y, z = np.indices((8, 8, 8)) cube1 = (x < 3) & (y < 3) & (z < 3) cube2 = (x >= 5) & (y >= 5) & (z >= 5) ax.voxels(cube1 | cube2, facecolors='royalblue', alpha=0.7) plt.show()
3D version of stem plot — drops vertical lines from each data point to the Z=0 plane. Useful for visualizing discrete 3D data where the floor projection helps interpret depth.
x = np.random.rand(20) y = np.random.rand(20) z = x + y ax.stem(x, y, z) plt.show()
3D arrow/quiver plot showing vectors in 3D space. Used for 3D electromagnetic fields, gradient vectors of 3D functions, and fluid dynamics in three dimensions.
X,Y,Z = np.meshgrid([0,1],[0,1],[0,1]) U = X; V = -Y; W = Z*0.5 ax.quiver(X,Y,Z,U,V,W, length=0.3) plt.show()
Fills the area between two curves in 3D space. Useful for depicting 3D ribbons, surfaces bounded by two paths, and confidence bands in 3D projections of time series.
t = np.linspace(0, 2*np.pi, 100) x1 = np.cos(t); y1 = np.sin(t); z1 = t x2 = np.cos(t)+0.3; y2=np.sin(t)+0.3; z2=t ax.fill_between(x1, y1, z1, x2, y2, z2, alpha=0.4); plt.show()
Special & Miscellaneous
6 chartsUses polar coordinates (r, θ) instead of Cartesian. Excellent for cyclic data, compass directions, and radar/spider charts that compare multiple attributes simultaneously.
fig, ax = plt.subplots(subplot_kw=dict(projection='polar')) theta = np.linspace(0, 2*np.pi, 100) r = 1 + np.sin(5*theta) # rose curve ax.plot(theta, r, color='crimson') plt.title('Polar Plot'); plt.show()
Displays a spectrogram — the short-time Fourier transform of a signal. Shows how frequency content evolves over time. Standard in audio analysis, speech processing, and vibration analysis.
Fs = 1000 # sample rate Hz t = np.linspace(0, 2, 2*Fs) # Chirp signal: freq grows over time x = np.sin(2*np.pi*(t + t**2)*50) plt.specgram(x, Fs=Fs, cmap='magma') plt.xlabel('Time'); plt.ylabel('Freq'); plt.show()
Visualizes non-zero positions in a sparse matrix. Essential for inspecting graph adjacency matrices, neural network connectivity, and the sparsity patterns in large linear systems.
from scipy.sparse import random as sprand A = sprand(100, 100, density=0.05).toarray() plt.spy(A, markersize=2, color='navy') plt.title('Sparse Matrix Sparsity') plt.show()
Log-scale axis plots. loglog uses log scale on both axes; semilogx/semilogy on one. Essential for data spanning many orders of magnitude like power laws and exponential growth.
x = np.logspace(-2, 3, 100) y = x**2.5 plt.loglog(x, y, label='Power Law x^2.5') # plt.semilogx(x, y) # log only x-axis # plt.semilogy(x, y) # log only y-axis plt.legend(); plt.show()
Draws horizontal bars with gaps — each series is composed of discrete horizontal segments. The go-to chart for Gantt scheduling, process timelines, and CPU/task scheduling visualization.
fig, ax = plt.subplots() ax.broken_barh( [(10,20),(40,15)], (0,9), facecolors='steelblue') ax.broken_barh( [(5,30),(45,10)], (10,9), facecolors='tomato') plt.show()
Plots the autocorrelation (acorr) or cross-correlation (xcorr) of a signal at various lags. Used in time series analysis to detect periodicity, seasonality, and signal relationships.
t = np.linspace(0, 10, 300) sig = np.sin(2*np.pi*t) + np.random.randn(300)*0.3 plt.acorr(sig, maxlags=50, lw=1.5) plt.xlabel('Lag'); plt.ylabel('Correlation') plt.title('Autocorrelation'); plt.show()
Relational Plots
3 chartsStatistical scatter plot with rich semantic encoding — hue, size, style can each map to data variables. Automatically handles legends and integrates directly with pandas DataFrames.
import seaborn as sns tips = sns.load_dataset('tips') sns.scatterplot( data=tips, x='total_bill', y='tip', hue='sex', size='size', style='smoker', palette='viridis', alpha=0.8) plt.show()
Line plot with automatic confidence interval bands when multiple observations exist per x-value. Aggregates repeated measurements and shows uncertainty — ideal for time series grouped by category.
flights = sns.load_dataset('flights') sns.lineplot(data=flights, x='year', y='passengers', hue='month', palette='tab20', linewidth=1.5) plt.legend(bbox_to_anchor=(1.05,1)) plt.show()
Figure-level function wrapping scatterplot/lineplot. Adds faceting across rows and columns with a single function call. Creates small multiples comparing the same relationship across subgroups.
sns.relplot( data=tips, x='total_bill', y='tip', col='time', # column facets hue='smoker', style='sex', kind='scatter', height=4) plt.show()
Distribution Plots
5 chartsEnhanced histogram with optional KDE overlay, bivariate support (2D histogram), and cumulative mode. Smarter bin selection than matplotlib's hist and tightly integrates with DataFrames.
penguins = sns.load_dataset('penguins') sns.histplot(data=penguins, x='flipper_length_mm', hue='species', kde=True, bins=20, multiple='stack', palette='Set2') plt.show()
Kernel Density Estimate — smooth continuous probability density using kernel smoothing. Supports univariate and bivariate (2D) KDE with filled contours. No binning artifacts.
# Univariate sns.kdeplot(data=penguins, x='body_mass_g', hue='species', fill=True, alpha=0.4) # Bivariate 2D sns.kdeplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', hue='species', levels=5); plt.show()
Empirical CDF with optional confidence bands and complementary (survival) mode. Groups can be compared on the same axes using hue. Better than histograms for comparing percentiles directly.
sns.ecdfplot(data=penguins, x='body_mass_g', hue='species', complementary=False) # True = survival fn plt.xlabel('Body Mass (g)') plt.show()
Draws tick marks along axes at each data point — a 1D "rug" showing every observation. Best used as an overlay on KDE or histogram to show exact data points at the axis margins.
sns.kdeplot(data=tips, x='total_bill', hue='time', fill=True) sns.rugplot(data=tips, x='total_bill', hue='time', height=0.04) plt.show()
Figure-level wrapper for all distribution plots (hist, kde, ecdf). Adds faceting by row/col, making it easy to compare distributions across multiple subgroups in a grid layout.
sns.displot( data=penguins, x='flipper_length_mm', col='species', row='sex', kind='hist', kde=True, height=3, aspect=0.8) plt.show()
Categorical Plots
8 chartsShows point estimates (mean by default) with confidence interval error bars for each category. Unlike a simple bar chart, it shows statistical uncertainty, not just the raw total.
sns.barplot(data=tips, x='day', y='total_bill', hue='sex', palette='pastel', capsize=0.1, errwidth=1.5) plt.title('Mean Bill by Day'); plt.show()
Bar chart that automatically counts occurrences of each category — no pre-aggregation needed. Perfect for frequency distributions of categorical columns in a DataFrame.
sns.countplot(data=tips, x='day', hue='smoker', palette='Set2', order=['Thur','Fri','Sat','Sun']) plt.title('Visit Count per Day'); plt.show()
Seaborn's boxplot adds easier categorical grouping, native hue support, and cleaner defaults over matplotlib's. Shows Q1/Q3/median/outliers with automatic notching for median confidence.
sns.boxplot(data=tips, x='day', y='total_bill', hue='sex', palette='Set3', notch=True, width=0.5) plt.show()
Seaborn's violin plot is the most feature-rich in any Python library — supports split violins (halving by hue), inner box/quartile/stick options, and bw_adjust for bandwidth control.
sns.violinplot(data=tips, x='day', y='tip', hue='sex', split=True, inner='quartile', palette='muted') plt.show()
Enhanced box plot ("letter-value plot") that shows many more quantiles with progressively narrower boxes. Provides much more detail about the tails and is better than boxplot for large datasets (>200 points).
diamonds = sns.load_dataset('diamonds') sns.boxenplot(data=diamonds, x='color', y='price', palette='viridis') plt.show()
Scatter plot along categorical axis with jitter to prevent overplotting. Shows every individual data point. Often combined with boxplot or violinplot to add raw observations to summary statistics.
# Combine with boxplot sns.boxplot(data=tips, x='day', y='tip', color='white', fliersize=0) sns.stripplot(data=tips, x='day', y='tip', hue='sex', dodge=True, alpha=0.5) plt.show()
Like stripplot but points are adjusted to never overlap using a beeswarm algorithm. Every point is visible without obscuring others. Gives a sense of distribution shape, especially for small samples.
sns.violinplot(data=tips, x='day', y='tip', color='lightblue', inner=None) sns.swarmplot(data=tips, x='day', y='tip', color='navy', size=3, alpha=0.7) plt.show()
Plots point estimates as dots connected by lines across categories. Better than barplot for visualizing interactions and trends across ordered categories, especially when comparing multiple hue groups.
sns.pointplot(data=tips, x='time', y='tip', hue='smoker', palette='Set1', dodge=True, capsize=0.1) plt.title('Mean Tip by Time'); plt.show()
Regression Plots
3 chartsScatter plot with a fitted regression line and confidence band. Supports linear, polynomial, logistic, and lowess smoothing. The simplest way to visualize and check relationships.
sns.regplot(data=tips, x='total_bill', y='tip', scatter_kws={'alpha':0.4}, line_kws={'color':'red'}, order=1) # order=2 for polynomial plt.show()
Figure-level regression plot that combines regplot with FacetGrid. Fits separate regression lines per hue group and supports row/col faceting, making it ideal for comparing trends across subgroups.
sns.lmplot(data=tips, x='total_bill', y='tip', hue='smoker', col='time', height=4, aspect=0.8, ci=95) # confidence interval plt.show()
Plots residuals of a linear regression against the predictor. A horizontal band around zero suggests a good linear fit; patterns indicate non-linearity, heteroscedasticity, or missing variables.
sns.residplot(data=tips, x='total_bill', y='tip', lowess=True, scatter_kws={'alpha':0.5}) plt.axhline(0, color='red', lw=1) plt.title('Residual Plot'); plt.show()
Matrix Plots
2 chartsColor-encodes 2D matrix data. Optionally annotates cells with values. The standard tool for correlation matrices, confusion matrices, feature importance matrices, and any tabular value heatmap.
corr = penguins.select_dtypes('number').corr() sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm', vmin=-1, vmax=1, square=True, linewidths=0.5) plt.title('Correlation Heatmap'); plt.show()
Hierarchically-clustered heatmap that reorders rows and columns by similarity (using linkage clustering) and adds dendrograms. Standard in bioinformatics for gene expression and proteomics analysis.
iris = sns.load_dataset('iris') X = iris.drop('species', axis=1) sns.clustermap(X, standardize=True, cmap='vlag', method='ward', figsize=(8,10)) plt.show()
Multi-Plot Grids
3 chartsCreates an NxN grid of scatter plots for every pair of numeric variables, with distribution plots on the diagonal. The single most powerful EDA starting point for multivariate datasets.
sns.pairplot(penguins, hue='species', diag_kind='kde', plot_kws={'alpha': 0.5}, corner=True) plt.show()
Shows the joint distribution of two variables in a central panel (scatter/KDE/hex) plus their marginal distributions (histogram/KDE) on the borders. Gives a complete bivariate picture in one chart.
sns.jointplot(data=penguins, x='bill_length_mm', y='bill_depth_mm', hue='species', kind='scatter') # or 'hex','kde','hist' plt.show()
A flexible grid of axes where different subsets of data are plotted in separate panels (facets). Allows any plot function to be applied per subplot, enabling powerful conditional visualizations.
g = sns.FacetGrid(tips, col='time', row='smoker', height=3) g.map_dataframe(sns.histplot, x='total_bill', kde=True) g.add_legend() plt.show()