Data Visualization with Matplotlib and Seaborn
A good chart answers one question clearly.
Choosing a chart
| Question | Chart |
|---|---|
| How is a variable distributed? | Histogram, box plot, violin plot |
| How do two numeric variables relate? | Scatter plot (plus a trend line) |
| How do categories compare? | Bar chart |
| How does something change over time? | Line chart |
| How are many variables correlated? | Heatmap of the correlation matrix |
| Parts of a whole (few categories) | Stacked bar (avoid pie with many slices) |
Matplotlib basics
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)", linestyle="--")
ax.set_title("Trigonometric functions")
ax.set_xlabel("x")
ax.set_ylabel("value")
ax.legend()
ax.grid(alpha=0.3)
fig.tight_layout()
fig.savefig("trig.png", dpi=150)
Seaborn for statistical plots
import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
sns.histplot(tips, x="total_bill", hue="time", kde=True)
plt.show()
sns.boxplot(tips, x="day", y="tip")
plt.show()
sns.scatterplot(tips, x="total_bill", y="tip", hue="smoker")
plt.show()
corr = tips.corr(numeric_only=True)
sns.heatmap(corr, annot=True, cmap="coolwarm", vmin=-1, vmax=1)
plt.show()
Design principles
- Label axes with units; title states the takeaway.
- Start bar charts at zero; truncated axes exaggerate differences.
- Use few colours; make them colour-blind safe (for example the
viridispalette). - Remove clutter: heavy borders, 3D effects, redundant legends.
- Annotate the important point instead of making readers search.
Common misleading charts
| Problem | Better |
|---|---|
| Truncated y-axis on a bar chart | Start at zero or use a dot plot |
| Dual axes with different scales | Two separate charts |
| Pie chart with 10 slices | Sorted bar chart |
| Cherry-picked time window | Show the full period |