Data Storytelling for Slides
Data Storytelling for Slides: Charts, graphs, data visualization, and narrative techniques for presenting data in presentations
Data Storytelling for Slides#
Turn raw data into compelling visual narratives that audiences understand, remember, and act on.
Core Principles#
1. Data Without Story Is Just Numbers#
A chart without context is meaningless. Every data point should serve a narrative: "Revenue grew 40% because we launched the mobile app" is a story. "Revenue was $1.2M" is just a number.
2. Show the Relationship, Not Just the Data#
The best data slides reveal relationships: cause and effect, before and after, actual vs. target, you vs. competition. Comparison is the foundation of insight.
3. Maximize the Data-Ink Ratio#
Remove anything in a chart that isn't data or essential context. Gridlines, borders, 3D effects, excessive labels — eliminate noise. Every pixel should either inform or guide.
4. The Audience Should Arrive at the Insight in 5 Seconds#
If a viewer can't understand the key takeaway within 5 seconds, the visualization has failed. Pre-attentive attributes (color, size, position) should make the insight immediately obvious.
Data Storytelling Maturity Model#
| Level | Chart Selection | Narrative Integration | Visual Design | Audience Impact |
|---|---|---|---|---|
| 1: Raw Data | Default chart type, no thought | No story — just numbers | Default Excel/Sheets colors | Confusing, ignored |
| 2: Basic Chart | Appropriate chart type | Chart title describes takeaway | Brand colors, clean labels | Understood but forgettable |
| 3: Annotated | Right chart for the question | Key points highlighted with annotations | Custom colors, callouts, footnotes | Remembered, shareable |
| 4: Narrative | Multi-chart flow tells a story | Data + text + visuals in harmony | Purposeful design, progressive disclosure | Drives action and decisions |
| 5: Immersive | Interactive exploration | Data narrative with branching paths | Cinematic, animated, multi-perspective | Changes behavior, memorable |
Target: Level 3 for internal dashboards and reports. Level 4 for investor and executive presentations.
Chart Selection Guide#
Choosing the Right Chart Type#
| Data Relationship | Recommended Chart | Why |
|-----------------------|----------------------------|--------------------------------|
| Comparison over time | Line chart | Shows trends, continuity |
| Part of a whole | Bar chart (stacked) or pie | Shows composition (limit to 5) |
| Ranking | Horizontal bar chart | Easy to compare lengths |
| Distribution | Histogram or box plot | Shows spread and outliers |
| Correlation | Scatter plot | Reveals relationships |
| Composition change | Stacked area chart | Shows parts over time |
| Flow / Funnel | Sankey or funnel chart | Shows conversion and drop-off |
| Geographic | Map (choropleth) | Spatial patterns |
| Progress to goal | Bullet chart / gauge | Actual vs. target |
| Relationship network | Network / node diagram | Connections and clusters |Chart Decision Flowchart#
What do you want to show?
1. Change over time? → Line chart or area chart
2. Compare categories? → Bar chart (horizontal for many categories)
3. Show composition? → Stacked bar (preferred) or pie chart (≤5 slices)
4. Distribution of data? → Histogram or box plot
5. Relationship between variables? → Scatter plot (add trend line)
6. Part-to-whole over time? → Stacked area chart
7. Progress to goal? → Bullet chart or progress bar
8. Flow between stages? → Sankey diagram or funnel
9. Geographic patterns? → Map visualizationWhen NOT to Use Pie Charts#
Avoid pie charts when:
- You have more than 5 categories (use stacked bar instead)
- You need precise comparisons (bars are better)
- The slices are similar in size (hard to distinguish)
- You want to show trends over time (use stacked area)
Only use pie charts when:
- You want to show part-of-whole with 2-4 categories
- The differences are obvious (e.g., 80% vs 20%)
- The audience needs a quick, intuitive understandingActionable Guidance#
Telling a Story with Data#
# The Three-Act Data Story
## ACT 1: Context
- What's the situation?
- What are we measuring and why?
- What's the time frame?
## ACT 2: The Insight
- What changed? (The "aha" moment)
- Why did it change? (Cause explanation)
- How significant is it? (Magnitude)
## ACT 3: Implication
- What should we do about it?
- What happens if we don't act?
- What's the expected outcome?The Data-Narrative Template#
# Data story template structure
data_story = {
"headline": "Revenue Grew 40% After Mobile Launch", # The takeaway
"context": {
"before": "Revenue was flat at $2M/month for 6 months",
"catalyst": "Mobile app launched in March 2024",
"after": "Revenue accelerated to $2.8M/month by June"
},
"evidence": {
"primary_chart": "Line chart showing revenue trajectory",
"supporting_data": "Mobile now accounts for 35% of all orders",
"statistical_significance": "p < 0.01, R² = 0.89"
},
"implication": {
"action": "Double down on mobile features and marketing",
"projection": "Projecting $4M/month by Q4 at current growth",
"risk": "Competitors also investing in mobile"
}
}
def format_data_slide(story_dict):
"""Generate a structured data slide from a story dictionary."""
slide = f"""
# {story_dict['headline']}
**Context**: {story_dict['context']['before']}
→ {story_dict['context']['catalyst']}
→ {story_dict['context']['after']}
[CHART: {story_dict['evidence']['primary_chart']}]
**Key Insight**: {story_dict['evidence']['supporting_data']}
**Action**: {story_dict['implication']['action']}
"""
return slideData-Ink Ratio#
What Is Data-Ink?#
Data-Ink = The ink (pixels) used to display data
Non-Data-Ink = Decorative elements, gridlines, borders, backgrounds
Data-Ink Ratio = Data-Ink / Total Ink Used in Visualization
Goal: Maximize the data-ink ratio (remove non-data ink without losing context)Before and After: Improving Data-Ink Ratio#
❌ POOR (Low data-ink ratio):
- 3D bar chart with shadows and gradients
- Background color with gradient
- Thick gridlines every interval
- Heavy borders around everything
- Decorative clip art
- Drop shadows on data points
- Excessive axis labels
✅ GOOD (High data-ink ratio):
- Flat, 2D design
- Minimal or no background fill
- Thin, light gridlines (or none)
- No chart borders
- Data points stand out with color
- Labels only where necessary
- Clean typographyApplying Data-Ink Principle#
# Concept: Removing non-data ink from a matplotlib chart
import matplotlib.pyplot as plt
import numpy as np
# Sample data
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
revenue = [120, 145, 160, 185, 210, 245]
# BAD: Low data-ink ratio
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# Bad chart
ax1.bar(months, revenue, color="skyblue", edgecolor="black", linewidth=1.5)
ax1.set_title("Bad: Low Data-Ink Ratio", fontsize=16, fontweight="bold")
ax1.set_facecolor("#f0f0f0") # Useless background
ax1.grid(True, axis="y", alpha=0.8, linewidth=1.5) # Heavy gridlines
ax1.spines["top"].set_visible(True)
ax1.spines["right"].set_visible(True)
ax1.spines["left"].set_linewidth(2)
ax1.spines["bottom"].set_linewidth(2)
# Lots of wasted ink
# Good chart
ax2.bar(months, revenue, color="#2B6CB0", width=0.6)
ax2.set_title("Good: High Data-Ink Ratio", fontsize=16, fontweight="bold")
ax2.set_facecolor("white")
ax2.grid(False) # No gridlines
ax2.spines["top"].set_visible(False)
ax2.spines["right"].set_visible(False)
ax2.spines["left"].set_color("#CBD5E0")
ax2.spines["bottom"].set_color("#CBD5E0")
ax2.tick_params(colors="#4A5568")
# Every pixel serves the data
plt.tight_layout()Pre-Attentive Attributes#
What Are Pre-Attentive Attributes?#
Pre-attentive attributes are visual properties that the brain processes in under 500 milliseconds — before conscious attention. Use them to direct the audience's eye to the most important insight instantly.
Key Pre-Attentive Attributes (ranked by effectiveness):
| Attribute | Best Used For | Example |
|--------------|-----------------------------------|--------------------------------------|
| Color (hue) | Highlighting a specific category | One bar in red, others in gray |
| Intensity | Showing magnitude or importance | Darker shade = higher value |
| Size | Showing quantity or hierarchy | Larger circle = more users |
| Position | Showing ranking or sequence | Top of list = highest ranked |
| Orientation | Showing difference or grouping | Angled element vs. straight |
| Shape | Categorizing different types | Circles for product, squares for service |
| Motion | Showing change or urgency | Animated growth (use sparingly) |The Highlighting Technique#
# Using pre-attentive attributes to highlight key data
import matplotlib.pyplot as plt
import numpy as np
def highlight_bar_chart(categories, values, highlight_index,
highlight_color="#E53E3E",
default_color="#CBD5E0"):
"""
Create a bar chart where one bar is highlighted using color.
This uses the pre-attentive attribute of color (hue) to direct attention.
"""
colors = [highlight_color if i == highlight_index else default_color
for i in range(len(categories))]
fig, ax = plt.subplots(figsize=(10, 6))
bars = ax.bar(categories, values, color=colors, width=0.6)
# Remove clutter
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_color("#E2E8F0")
ax.spines["bottom"].set_color("#E2E8F0")
ax.grid(False)
# Add value labels
for bar, value in zip(bars, values):
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,
f"{value}", ha="center", va="bottom",
fontsize=12, fontweight="bold" if value == max(values) else "normal",
color="#2D3748")
ax.set_title("Revenue by Channel", fontsize=16, fontweight="bold", pad=20)
return fig
# Example
categories = ["Direct", "Organic", "Paid Ads", "Social", "Referral"]
values = [45, 120, 85, 60, 40]
# Highlight the highest value (Organic)
# chart = highlight_bar_chart(categories, values, highlight_index=1)Dashboard Slide Design#
Dashboard Structure for Presentations#
Executive Dashboard Layout:
┌──────────────────────────────────────────────────┐
│ HEADER: Key Metric + Trend (Large, Center) │
│ [KPI: $1.2M ARR] [↑ 40% YoY] │
├──────────┬──────────┬──────────┬─────────────────┤
│ KPI 1 │ KPI 2 │ KPI 3 │ KPI 4 │
│ Revenue │ Users │ Retention│ NPS │
│ $X │ X,XXX │ XX% │ XX │
│ ↑ X% │ ↑ X% │ ↓ X% │ → X pts │
├──────────┴──────────┴──────────┴─────────────────┤
│ Main Chart Area (largest real estate) │
│ [Line chart showing trend over time] │
│ │
├──────────────────────────────────────────────────┤
│ Supporting Detail / Breakdown │
│ [Secondary chart or table] │
└──────────────────────────────────────────────────┘KPI Presentation Patterns#
## KPI Slide Patterns
### Single KPI (Hero Metric)
[Large Number] → $1,200,000
[Label] → Annual Recurring Revenue
[Trend Arrow] → ↑ 40% year-over-year
[Sparkline] → [Mini line chart showing trend]
[Context] → "On track to hit $2M by Q4"
### Multiple KPIs (Dashboard Style)
| Metric | Value | Trend | vs Target | Sparkline |
|--------------|-----------|-------|-----------|-----------|
| ARR | $1.2M | ↑ 40% | ✓ On track| [mini ln] |
| Active Users | 45,000 | ↑ 22% | ✓ Ahead | [mini ln] |
| Churn Rate | 3.2% | ↓ 0.5%| ⚠ Watch | [mini ln] |
| NPS | 62 | ↑ 5pts| ✓ Good | [mini ln] |
### Waterfall KPI
[Starting Point] → [Change 1] → [Change 2] → [Change 3] = [Result]Annotated Charts#
Annotation Styles#
Five Essential Annotation Types:
1. **Callout Box**: Highlight a specific point with a text box + arrow
- Use for: Key inflection points, record highs/lows
2. **Trend Line**: A line showing the overall direction
- Use for: Emphasizing growth despite fluctuations
3. **Threshold Line**: A horizontal/vertical line marking a target
- Use for: Showing progress toward a goal
4. **Data Label**: Direct label on a specific data point
- Use for: The MOST important point only (not all points)
5. **Comparative Callout**: "vs. Industry Average" label
- Use for: Contextualizing performanceAnnotation Best Practices#
DO:
- Annotate ONE key insight per chart
- Use arrows or lines to clearly connect annotation to data point
- Keep annotations short (8-12 words max)
- Use a contrasting color for the annotation
- Place annotations in empty space (not over data)
DON'T:
- Annotate every interesting point (overwhelming)
- Use annotations that explain what's already obvious
- Make annotations larger than the data itself
- Forget to include units or contextAnnotated Chart Example#
# Creating an annotated chart for presentations
import matplotlib.pyplot as plt
import numpy as np
def annotated_revenue_chart():
"""Create a line chart with strategic annotations."""
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
revenue = [200, 210, 205, 220, 260, 300, 320, 350, 380, 420, 460, 510]
fig, ax = plt.subplots(figsize=(12, 6))
# Main line
ax.plot(months, revenue, color="#2B6CB0", linewidth=2.5, zorder=2)
ax.fill_between(range(len(months)), revenue, alpha=0.1, color="#2B6CB0")
# Annotation 1: Product launch inflection point
ax.annotate(
"Mobile App\nLaunch", # Label
xy=(4, 260), # Point being annotated
xytext=(2, 350), # Where to place the text
fontsize=12, fontweight="bold", color="#E53E3E",
arrowprops=dict(arrowstyle="->", color="#E53E3E", linewidth=2),
bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="#E53E3E")
)
# Annotation 2: Key result
ax.annotate(
"Record: $510K\n↑ 155% YoY",
xy=(11, 510),
xytext=(9, 540),
fontsize=12, fontweight="bold", color="#38A169",
arrowprops=dict(arrowstyle="->", color="#38A169", linewidth=2),
bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="#38A169")
)
# Clean design
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_color("#CBD5E0")
ax.spines["bottom"].set_color("#CBD5E0")
ax.grid(True, alpha=0.3, axis="y")
ax.tick_params(colors="#4A5568")
ax.set_title("Monthly Revenue — $510K in Record December",
fontsize=16, fontweight="bold", pad=20)
ax.set_ylabel("Revenue ($K)", fontsize=12, color="#4A5568")
return figAvoiding Misleading Visuals#
Common Data Visualization Traps#
| Trap | Why It's Misleading | How to Fix |
|------------------------|----------------------------------------------|-----------------------------------------|
| Truncated Y-Axis | Exaggerates small differences | Start axis at 0 (or clearly mark break) |
| 3D Charts | Distorts proportions, hard to read | Use flat 2D charts |
| Cherry-picked timeframe | Shows favorable data, hides full picture | Show full timeline |
| Dual axes manipulation | Makes unrelated trends look correlated | Use separate charts or clarify |
| Pie chart with 10+ slices | Tiny slices are unreadable | Aggregate into "Other" or use bar chart |
| Area charts not starting at 0 | Exaggerates growth | Always start area charts at 0 |
| Color misuse | Red = bad, green = good (cultural bias) | Use color consistently, add labels |
| Inconsistent scales | Makes comparison impossible | Use the same scale for related charts |
| No baseline | Changes look bigger/smaller than reality | Always include a comparison baseline |
| Selectively omitted data | Hides context, skews perception | Show all relevant data, mark outliers |The Y-Axis Rule#
Bar charts and area charts MUST start at zero.
Line charts CAN have a non-zero baseline but should indicate it.
✅ Bar chart starting at 0: [||||||||||] = 100%
❌ Bar chart starting at 80: [|||] = Looks like 15% but is actually 80%
Exception: Line charts for small fluctuations (e.g., stock prices)
can zoom in — but clearly mark the axis break or use a sparkline.Data Sources & Citations on Slides#
Citation Format#
Required elements for data citations on slides:
1. Source name (organization, publication)
2. Publication date or data collection period
3. URL or DOI (if public)
4. Methodology note (if relevant)
Format: "Source: [Organization], [Year]. [URL]"
Examples:
- "Source: Gartner, 2024. gartner.com/market-report"
- "Source: Internal data, Jan-Dec 2024 (n=10,000 users)"
- "Source: US Census Bureau, 2023. census.gov/data"Citation Placement#
- Place citations at the bottom of the slide (footer area)
- Use 10-12pt font in a neutral color (gray)
- Keep consistent position on every slide with data
- For critical numbers, include the citation on the same slide
- For sensitive data, mark: "Source: [Company] Internal Data — Confidential"Interactive vs Static Data Slides#
When to Use Each#
| Context | Recommendation | Reason |
|--------------------------|-------------------------|-------------------------------------|
| Live presentation | Static chart | Audience doesn't interact anyway |
| Email / PDF | Static + summary table | Reader can't click |
| Board meeting | Static + printed backup | Focus on discussion |
| Executive review | Static with drill-downs | PDF with appendix |
| Data room / due diligence| Interactive dashboard | Investors want to explore |
| Internal weekly report | Interactive preferred | Team needs to filter and slice |
| Conference presentation | Static (high impact) | One message, perfectly framed |Static Chart Best Practices#
For static slides (presentations, PDFs):
- Include the key insight in the title (not "Revenue by Quarter" but "Revenue Grew 40%")
- Add minimal annotations directly on the chart
- Include a "source" and "methodology" footnote
- Show the data table alongside if precision matters
- Use callouts for the 1-2 most important data pointsCommon Mistakes#
- Chart junk: 3D effects, excessive gridlines, clip art, and useless decorations that distract from the data.
- Wrong chart type: Using pie charts for 12 categories, or line charts for categorical data. Match chart to data relationship.
- Missing context: Showing a metric without a comparison (period-over-period, vs. target, vs. industry). Data alone is meaningless.
- No narrative: Charts displayed without explanation or insight. The audience is left to figure it out themselves.
- Data overload: Too many metrics, too many data points, too many charts. One insight per slide. Prioritize ruthlessly.
- Misleading scales: Truncated Y-axes, inconsistent scales across comparison charts, or dual axes that imply false correlation.
- No source attribution: Data without a source is untrustworthy. Always cite where numbers come from.
- Highlighting everything: Making all bars in a chart different colors. If everything is highlighted, nothing is.
- Small fonts on charts: Axis labels, legends, and annotations too small to read when projected. Minimum 12pt for any chart text.
- No takeaway title: A chart titled "Revenue by Quarter" tells me what it is, not what I should learn. Use insight-driven titles.
More in Presentation
View all →Pitch Deck Creation
Pitch Deck Creation: Investor pitch decks, Y Combinator applications, Product Hunt launches, and startup fundraising presentations
Presentation Design & Storyboarding
Presentation Design & Storyboarding: Slide design principles, visual hierarchy, layout, typography, and storyboarding for compelling presentations
Presentation Automation
Presentation Automation: python-pptx, Google Slides API, automated slide generation from data and templates