Thursday, September 10, 2026
HomeData ScienceData Visualisation with Matplotlib & Seaborn – Complete Guide 2026

Data Visualisation with Matplotlib & Seaborn – Complete Guide 2026

Table of Content

A great visualisation can communicate a finding in seconds that a table of numbers cannot convey in minutes. Matplotlib is Python’s foundational plotting library — powerful and precise, but verbose. Seaborn builds on Matplotlib to provide beautiful statistical charts with minimal code. This guide covers both, from quick exploratory plots to publication-quality figures.

Matplotlib Fundamentals

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Figure and axes objects — the right way to use Matplotlib
fig, ax = plt.subplots(figsize=(10, 6))

x = np.linspace(0, 4 * np.pi, 200)
ax.plot(x, np.sin(x), label='sin(x)', linewidth=2, color='steelblue')
ax.plot(x, np.cos(x), label='cos(x)', linewidth=2, color='tomato', linestyle='--')

ax.set_title('Trigonometric Functions', fontsize=16, fontweight='bold', pad=15)
ax.set_xlabel('x (radians)', fontsize=13)
ax.set_ylabel('Amplitude', fontsize=13)
ax.legend(fontsize=12)
ax.grid(True, alpha=0.3)
ax.set_xlim(0, 4 * np.pi)
ax.set_ylim(-1.3, 1.3)
ax.spines[['top', 'right']].set_visible(False)

plt.tight_layout()
plt.savefig('trig.png', dpi=150, bbox_inches='tight')
plt.show()

Common Chart Types

stock market candlestick chart on dark screen
Photo by Maxim Hopman on Unsplash
np.random.seed(42)
df = pd.DataFrame({
    'month':    pd.date_range('2025-01', periods=12, freq='ME'),
    'revenue':  np.cumsum(np.random.normal(10000, 2000, 12)) + 50000,
    'region':   np.random.choice(['North', 'South', 'East', 'West'], 12),
    'score':    np.random.normal(70, 15, 12).clip(0, 100)
})

fig, axes = plt.subplots(2, 3, figsize=(16, 9))

# Line chart
axes[0, 0].plot(df['month'], df['revenue'], 'o-', color='steelblue')
axes[0, 0].set_title('Revenue Over Time'); axes[0, 0].tick_params(axis='x', rotation=45)

# Bar chart
region_rev = df.groupby('region')['revenue'].mean().sort_values()
axes[0, 1].barh(region_rev.index, region_rev.values, color='steelblue', edgecolor='white')
axes[0, 1].set_title('Avg Revenue by Region')

# Histogram
axes[0, 2].hist(df['score'], bins=8, color='steelblue', edgecolor='white', alpha=0.8)
axes[0, 2].axvline(df['score'].mean(), color='red', linestyle='--', label=f'Mean={df["score"].mean():.1f}')
axes[0, 2].legend(); axes[0, 2].set_title('Score Distribution')

# Scatter plot
x2 = np.random.normal(0, 1, 200); y2 = 2 * x2 + np.random.normal(0, 0.5, 200)
axes[1, 0].scatter(x2, y2, alpha=0.5, s=20, color='steelblue')
z = np.polyfit(x2, y2, 1)
axes[1, 0].plot(sorted(x2), np.poly1d(z)(sorted(x2)), 'r-')
axes[1, 0].set_title('Scatter with Trend')

# Box plot
data_box = [np.random.normal(loc, 1, 100) for loc in [0, 1, 2, 1.5]]
bp = axes[1, 1].boxplot(data_box, labels=['A', 'B', 'C', 'D'], patch_artist=True)
for patch, color in zip(bp['boxes'], ['steelblue', 'tomato', 'green', 'orange']):
    patch.set_facecolor(color)
axes[1, 1].set_title('Distribution by Group')

# Pie chart
sizes = [35, 25, 20, 20]
axes[1, 2].pie(sizes, labels=['North', 'South', 'East', 'West'],
               autopct='%1.0f%%', startangle=90,
               colors=['steelblue', 'tomato', 'green', 'orange'])
axes[1, 2].set_title('Revenue Share by Region')

plt.suptitle('Sales Dashboard', fontsize=18, fontweight='bold', y=1.01)
plt.tight_layout()
plt.savefig('dashboard.png', dpi=150, bbox_inches='tight')
plt.show()

Seaborn for Statistical Visualisation

import seaborn as sns

# Load a real dataset
iris    = sns.load_dataset('iris')
tips    = sns.load_dataset('tips')
flights = sns.load_dataset('flights')

# Global style
sns.set_theme(style='whitegrid', palette='muted', font_scale=1.2)

# Distribution plots
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
sns.histplot(iris['sepal_length'], kde=True, ax=axes[0])
sns.boxplot(data=iris, x='species', y='sepal_length', ax=axes[1])
sns.violinplot(data=iris, x='species', y='sepal_length',
               inner='quartile', ax=axes[2])
plt.tight_layout(); plt.show()

Heatmap and Pair Plot

a computer screen with a bar chart on it
Photo by 1981 Digital on Unsplash
# Correlation heatmap
fig, ax = plt.subplots(figsize=(8, 6))
corr = iris.drop('species', axis=1).corr()
sns.heatmap(corr, annot=True, fmt='.2f', cmap='RdYlGn',
            center=0, square=True, linewidths=0.5, ax=ax)
ax.set_title('Feature Correlation Matrix')
plt.tight_layout(); plt.show()

# Pair plot — relationships between all feature pairs
g = sns.pairplot(iris, hue='species', diag_kind='kde',
                 plot_kws={'alpha': 0.6, 's': 40})
g.fig.suptitle('Iris Feature Pair Plot', y=1.02)
plt.show()

# FacetGrid — same plot across subgroups
g = sns.FacetGrid(tips, col='time', row='smoker', margin_titles=True)
g.map(sns.scatterplot, 'total_bill', 'tip', alpha=0.7)
g.add_legend()
plt.show()

Advanced Seaborn Charts

# Heatmap of flights pivot table
pivot = flights.pivot_table(index='month', columns='year', values='passengers')
plt.figure(figsize=(12, 6))
sns.heatmap(pivot, fmt='d', annot=True, cmap='YlOrRd', linewidths=0.3)
plt.title('Passenger Counts by Month and Year')
plt.tight_layout(); plt.show()

# Regression plot
plt.figure(figsize=(8, 5))
sns.regplot(data=tips, x='total_bill', y='tip',
            scatter_kws={'alpha': 0.5}, line_kws={'color': 'red'})
plt.title('Tip vs Total Bill with Regression Line')
plt.show()

# Count and bar plots
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.countplot(data=tips, x='day', hue='sex', ax=axes[0])
sns.barplot(data=tips, x='day', y='tip', hue='sex',
            estimator='mean', ci=95, ax=axes[1])
axes[0].set_title('Count by Day and Sex')
axes[1].set_title('Mean Tip by Day and Sex')
plt.tight_layout(); plt.show()

Publication-Quality Figures

# Publication style
plt.rcParams.update({
    'font.family':     'serif',
    'font.size':       11,
    'axes.titlesize':  13,
    'axes.labelsize':  11,
    'xtick.labelsize': 10,
    'ytick.labelsize': 10,
    'legend.fontsize': 10,
    'figure.dpi':      150,
    'axes.spines.top':   False,
    'axes.spines.right': False,
})

fig, ax = plt.subplots(figsize=(7, 4.5))
# ... your plot ...
plt.tight_layout()
plt.savefig('figure1.pdf', format='pdf', bbox_inches='tight')  # vector
plt.savefig('figure1.png', format='png', dpi=300, bbox_inches='tight')  # raster

Conclusion

Use Matplotlib when you need precise control over every element of the figure. Use Seaborn for statistical charts — its one-liners produce publication-quality output that would take 20 lines in raw Matplotlib. For interactive charts, switch to Plotly (plotly.express is Seaborn’s interactive equivalent). For embedded dashboards, use Streamlit or Plotly Dash. Whatever the tool, the most important skill is not the code — it is choosing the right chart type for the question you are answering.

Leave feedback about this

  • Rating

Durgesh Kekare
Durgesh Kekarehttps://www.dataexpertise.in
Durgesh Kekare is a data science educator and founder of DataExpertise.in. With expertise in Python, machine learning, and analytics, he helps 10,000+ learners break into data careers.

Latest Posts

List of Categories