Python Data Visualization, SQL Connectivity & EDA
Back to HIGH-IMPACT VISUAL STORYTELLING: MATPLOTLIB & SEABORN

Visualizing Multidimensional Data: Scatter Plots, Color Encodings & Log Scales

Guide to multi-variable scatter plots, color mapping (cmap), size encodings, and logarithmic scale adjustments.

5 minutesReading
๐ŸŽฏ Free Guest Mode: You are learning for free. Sign in to save your completion progress and quiz answers.

One Scatter Plot, Four Insights: Color, Size & Log Scales

You just learned plt.plot(x, y) โ€” two variables, one line. Your boss now asks: "Show me spend vs revenue, but also which campaigns were most profitable and which reached the most customers โ€” in one chart for the deck." That is 4 variables and you have a 2D screen. This article shows how color, size, and log scales turn a plain scatter into a 4-dimensional story โ€” using a 5-row campaign table you can picture immediately.

1. The Data: 5 Campaigns, 4 Numbers Each

Same e-commerce context as the rest of the course โ€” each row is a marketing campaign:

CampaignSpend ($)Revenue ($)Profit Margin (%)Customers Reached
Summer Sale10,00042,000188,200
Influencer Push35,00095,000313,100
Email Blast2,00018,0004212,400
TV Spot120,000210,000121,800
Referral Bonus8,00038,000356,500

Plotting only x=spend, y=revenue hides that Email Blast (tiny spend, 42% margin, 12K customers) was the most efficient and TV Spot (huge spend, 12% margin) was wasteful. Let's encode the other two columns visually.

2. 4 Dimensions on a 2D Screen โ€” How Each Channel Maps

Visual ChannelData ColumnParameterWhat the Viewer Sees
Horizontal positionSpendx=Left = cheap, Right = expensive
Vertical positionRevenuey=Bottom = low revenue, Top = high
ColorProfit Marginc= + cmap='viridis'Dark purple = thin margin, Yellow = fat margin (colorbar tells the scale)
Dot sizeCustomers Reacheds=Small dot = niche, Big bubble = mass reach

3. The Code โ€” Read It as "One Line Per Dimension"

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))

#  x and y      โ†’  spend vs revenue
#  c + cmap     โ†’  profit margin as color
#  s            โ†’  customers as bubble size
#  alpha        โ†’  transparency so overlapping bubbles stay readable
scatter = plt.scatter(
    x=df['marketing_spend'],
    y=df['revenue'],
    c=df['profit_margin'],       # 3rd dimension: color
    cmap='viridis',              # yellow = high margin, purple = low margin
    s=df['customer_count'] / 10, # 4th dimension: bubble size (divide to fit screen)
    alpha=0.65,                  # see-through so overlaps don't hide
    edgecolors='w', linewidth=0.5
)

cbar = plt.colorbar(scatter)
cbar.set_label('Profit Margin (%)', fontsize=11)

plt.xlabel('Marketing Spend ($)', fontsize=12)
plt.ylabel('Revenue Generated ($)', fontsize=12)
plt.title('Campaign Performance: Spend vs Revenue & Profitability', fontsize=14, fontweight='bold')
plt.grid(True, linestyle='--', alpha=0.5)
plt.tight_layout()
plt.show()

Executive read: Email Blast is a small yellow bubble high up on the left โ€” low spend, high margin, big reach. TV Spot is a dark purple dot far right โ€” expensive, low margin, tiny reach. One chart, one decision: shift budget from TV to Email.

4. When Dots Pile Up: Log Scales

Some metrics span orders of magnitude โ€” YouTube views from 1,000 to 100,000,000, or revenue from $45 to $1.2M. On a linear axis, 90% of dots crush into the bottom-left corner and the trend disappears.

Fix: plt.xscale('log') or plt.yscale('log') โ€” each tick is ร—10, so 1K, 10K, 100K, 1M get equal space. Hidden linear relationships suddenly appear along a diagonal.

# Before: plt.scatter(x=df['views'], y=df['revenue'])  # dots crushed
plt.xscale('log')   # spread the x-axis logarithmically
plt.yscale('log')   # optionally both axes
plt.show()

When a prompt says "extreme magnitudes / power-law / bunching in corner" โ†’ think log scale. This is Quiz 2 Q12.

5. Quick Tip: Long Labels โ†’ Go Horizontal

Category names like "Home & Kitchen โ€” Small Appliances" overlap when tilted. Use plt.barh() (horizontal bars) instead of plt.bar() โ€” same data, labels stay readable. Seaborn equivalent: sns.barplot(..., orient='h').

Loading progress...