🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
NEWSLIVESearch All Content
💼 Servicesℹ️ About✉️ ContactView Pricing Plansfrom $10

Matplotlib and Seaborn: Data Visualization

Module 3: Visualization🟢 Free Lesson

Advertisement

Matplotlib and Seaborn: Data Visualization

The Grammar of Graphics

Data visualization is the graphical representation of information and data. A good visualization tells a story and reveals patterns that numbers alone cannot.

The Grammar of Graphics PipelineDataRaw datasetAestheticsx, y, color, sizeGeometriesPoints, lines, barsStatisticsSmooth, bin, modelThemeFonts, colors, gridLibrary Mapping:Matplotlib: Low-levelSeaborn: StatisticalPlotly: InteractiveKey Principle: Data → Aesthetics → Geometries → Statistics → Coordinates → Facets → Theme

Matplotlib: The Foundation

Basic Plot Structure

Matplotlib Figure AnatomyFigureAxesPlot Area (lines, bars, scatter)X-axis LabelY-axis LabelTitleLegend
python
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Figure anatomy — object-oriented interface
x = np.linspace(0, 10, 100)
y = np.sin(x)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, y, label='sin(x)', color='blue', linewidth=2)
ax.set_xlabel('X Axis', fontsize=12)
ax.set_ylabel('Y Axis', fontsize=12)
ax.set_title('Basic Line Plot', fontsize=14)
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Essential Plot Types

Choosing the Right Plot TypeLine ChartTrends over timeUse: Time seriesBar ChartCategory comparisonUse: CategoriesScatter PlotRelationshipsUse: CorrelationHistogramDistribution shapeUse: DistributionsBox PlotFive-number summaryUse: OutliersHeatmapCorrelation matrixUse: MultivariateViolin PlotDistribution + densityUse: Dense dist.
python
# Line Plot (trends over time)
dates = pd.date_range('2024-01-01', periods=12)
values = np.random.randn(12).cumsum() + 100

fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(dates, values, marker='o', linestyle='-', color='#2196F3')
ax.fill_between(dates, values - 10, values + 10, alpha=0.2)
ax.set_title('Stock Price Trend')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

# Bar Plot (comparisons)
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]

fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].bar(categories, values, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
axes[0].set_title('Vertical Bar Plot')
axes[1].barh(categories, values, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'])
axes[1].set_title('Horizontal Bar Plot')
plt.tight_layout()
plt.show()

# Scatter Plot (relationships)
x = np.random.randn(100)
y = x * 2 + np.random.randn(100) * 0.5
colors = np.random.rand(100)
sizes = np.random.rand(100) * 200

plt.figure(figsize=(10, 6))
scatter = plt.scatter(x, y, c=colors, s=sizes, alpha=0.6, cmap='viridis')
plt.colorbar(scatter)
plt.title('Scatter Plot with Color and Size')
plt.show()

Subplots and Layouts

python
# Complex layout with GridSpec
import matplotlib.gridspec as gridspec

fig = plt.figure(figsize=(14, 10))
gs = gridspec.GridSpec(3, 3, figure=fig)

# Large plot spanning 2 rows, 2 columns
ax_main = fig.add_subplot(gs[0:2, 0:2])
ax_main.plot(x, y, 'b-')
ax_main.set_title('Main Plot')

# Side plots
ax_right1 = fig.add_subplot(gs[0, 2])
ax_right1.barh(categories[:3], values[:3])

ax_right2 = fig.add_subplot(gs[1, 2])
ax_right2.pie(sizes[:3], labels=labels[:3])

# Bottom plot
ax_bottom = fig.add_subplot(gs[2, :])
ax_bottom.plot(x, np.sin(x) * 100, 'r-')
ax_bottom.set_title('Bottom Plot')

plt.tight_layout()
plt.show()

Seaborn: Statistical Visualization

Distribution Plots

python
import seaborn as sns

sns.set_theme(style="whitegrid")
tips = sns.load_dataset('tips')

# Histogram with KDE
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.histplot(data=tips, x='total_bill', kde=True, ax=axes[0])
axes[0].set_title('Histogram with KDE')
sns.histplot(data=tips, x='total_bill', hue='time', kde=True, ax=axes[1])
axes[1].set_title('Histogram by Time')
plt.tight_layout()
plt.show()

# KDE Plot
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.kdeplot(data=tips, x='total_bill', fill=True, ax=axes[0])
axes[0].set_title('KDE Plot')
sns.kdeplot(data=tips, x='total_bill', hue='day', fill=True, ax=axes[1])
axes[1].set_title('KDE by Day')
plt.tight_layout()
plt.show()

Categorical Plots

python
# Box Plot
plt.figure(figsize=(12, 6))
sns.boxplot(data=tips, x='day', y='total_bill', hue='sex')
plt.title('Total Bill by Day and Gender')
plt.show()

# Violin Plot
plt.figure(figsize=(12, 6))
sns.violinplot(data=tips, x='day', y='total_bill', hue='sex', split=True)
plt.title('Violin Plot')
plt.show()

# Swarm Plot
plt.figure(figsize=(12, 6))
sns.swarmplot(data=tips, x='day', y='total_bill', hue='sex', size=4)
plt.title('Swarm Plot')
plt.show()

Relationship Plots

python
# Scatter Plot with Regression
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.scatterplot(data=tips, x='total_bill', y='tip', ax=axes[0])
axes[0].set_title('Basic Scatter')
sns.regplot(data=tips, x='total_bill', y='tip', ax=axes[1])
axes[1].set_title('Scatter with Regression')
plt.tight_layout()
plt.show()

# Joint Plot
g = sns.jointplot(data=tips, x='total_bill', y='tip', kind='scatter')
plt.show()

# Pair Plot (matrix of relationships)
iris = sns.load_dataset('iris')
g = sns.pairplot(iris, hue='species')
plt.show()

# Heatmap (correlation matrix)
plt.figure(figsize=(10, 8))
corr = tips.select_dtypes(include=[np.number]).corr()
sns.heatmap(corr, annot=True, cmap='coolwarm', center=0,
            square=True, linewidths=0.5)
plt.title('Correlation Heatmap')
plt.show()

Matrix Plots

python
# FacetGrid for complex layouts
g = sns.FacetGrid(tips, col='time', row='sex', height=4, aspect=1.2)
g.map_dataframe(sns.histplot, x='total_bill', bins=15)
g.set_titles('{row_name} - {col_name}')
plt.show()

# PairGrid
g = sns.PairGrid(iris, hue='species')
g.map_upper(sns.scatterplot)
g.map_lower(sns.kdeplot)
g.map_diag(sns.histplot)
g.add_legend()
plt.show()

Customization and Themes

python
# Set theme
sns.set_theme(style="whitegrid", palette="muted")

# Custom color palettes
palette = sns.color_palette("husl", 10)
sns.set_palette(palette)

# Custom styling
plt.rcParams.update({
    'figure.figsize': (10, 6),
    'font.size': 12,
    'axes.titlesize': 14,
    'axes.labelsize': 12,
    'figure.dpi': 100,
    'savefig.dpi': 300,
    'savefig.bbox': 'tight'
})
Seaborn Color PalettesSequential:viridisDiverging:RdBu_rQualitative:Set1Sequential = ordered data | Diverging = ± center | Qualitative = categoriesColorblind-safe palettes: Use "colorblind" or "deep" for accessibility

Publication-Quality Visualizations

python
def create_publication_plot(data, x, y, hue=None, title="", filename=None):
    sns.set_theme(style="whitegrid", context="paper")
    fig, ax = plt.subplots(figsize=(8, 6))

    if hue:
        sns.scatterplot(data=data, x=x, y=y, hue=hue, s=100, alpha=0.7, ax=ax)
    else:
        sns.scatterplot(data=data, x=x, y=y, s=100, alpha=0.7, ax=ax)

    ax.set_title(title, fontsize=14, fontweight='bold', pad=20)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.grid(True, alpha=0.3, linestyle='--')
    plt.tight_layout()

    if filename:
        plt.savefig(f'{filename}.png', dpi=300, bbox_inches='tight')
        plt.savefig(f'{filename}.pdf', bbox_inches='tight')
    plt.show()

Practical Example: Sales Dashboard

python
np.random.seed(42)
dates = pd.date_range('2024-01-01', '2024-12-31', freq='D')
products = ['Product A', 'Product B', 'Product C']
regions = ['North', 'South', 'East', 'West']

data = {
    'date': np.random.choice(dates, 500),
    'product': np.random.choice(products, 500),
    'region': np.random.choice(regions, 500),
    'sales': np.random.randint(100, 1000, 500),
    'quantity': np.random.randint(1, 50, 500)
}
df = pd.DataFrame(data)
df['revenue'] = df['sales'] * df['quantity']

# Create dashboard
fig = plt.figure(figsize=(16, 12))
gs = fig.add_gridspec(3, 3, hspace=0.3, wspace=0.3)

ax1 = fig.add_subplot(gs[0, :2])
daily_sales = df.groupby('date')['revenue'].sum()
ax1.plot(daily_sales.index, daily_sales.values, color='#2196F3', linewidth=1)
ax1.fill_between(daily_sales.index, daily_sales.values, alpha=0.2)
ax1.set_title('Daily Revenue Trend', fontweight='bold')

ax2 = fig.add_subplot(gs[0, 2])
product_revenue = df.groupby('product')['revenue'].sum()
ax2.pie(product_revenue, labels=product_revenue.index, autopct='%1.1f%%',
        colors=['#FF6B6B', '#4ECDC4', '#45B7D1'])
ax2.set_title('Revenue by Product')

ax3 = fig.add_subplot(gs[1, :2])
region_product = df.groupby(['region', 'product'])['revenue'].sum().unstack()
region_product.plot(kind='bar', ax=ax3, colormap='Set2')
ax3.set_title('Revenue by Region & Product')

ax4 = fig.add_subplot(gs[1, 2])
sns.histplot(data=df, x='sales', kde=True, ax=ax4, color='#45B7D1')
ax4.set_title('Sales Distribution')

plt.suptitle('Sales Dashboard 2024', fontsize=16, fontweight='bold', y=1.02)
plt.show()

Key Takeaways

Practice Exercise

  1. Create a multi-panel figure with 4 different plot types using plt.subplots(2, 2)
  2. Customize colors, fonts, and layout using sns.set_theme and plt.rcParams
  3. Build a Seaborn FacetGrid that facets a dataset by two categorical variables
  4. Compute and visualize a correlation heatmap with annotations
  5. Create a publication-quality scatter plot with regression line, removing top/right spines
  6. Export your final figure in both PNG (300 DPI) and PDF formats
  7. Build a mini-dashboard with at least 5 panels summarizing a dataset
—
☆☆☆☆☆
0 ratings

Rate & Feedback

Need Expert Data Science Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement