The Chart Selection Framework
Choosing the right chart isn't about memorizing 50 chart types. It's about asking the right questions about your data story.
The Three Questions Framework
Every visualization answers one question. Before choosing a chart, identify which:
1. What is your data relationship?
- Comparison (categorical differences)
- Trend (change over time)
- Distribution (data shape and spread)
- Composition (part-to-whole)
- Relationship (correlation between variables)
- Geographic (spatial patterns)
2. How many variables do you have?
- Single variable (one metric)
- Two variables (X and Y)
- Three variables (X, Y, and size/color)
- Multiple categories (grouped/stacked)
3. How many data points?
- Few (2-10): Detailed labels, emphasis on precise values
- Medium (10-50): Focus on patterns, less detailed labels
- Many (50+): Aggregate or use distributions
Example: Flipkart Product Sales
Scenario: You have sales data for 8 product categories.
Question 1: What relationship? → Comparison (which category sold most?) Question 2: How many variables? → Single variable (sales by category) Question 3: How many data points? → Few (8 categories)
Answer: Horizontal bar chart, sorted by sales (highest first)
Why not pie chart? 8 slices make precise comparison hard. Bar length is more accurate than angle. Why horizontal? Category labels ("Home & Kitchen") are long — horizontal bars fit them better. Why sorted? Reader's question is "which sold most?" — sorting makes answer instant.
Choosing a chart is like choosing transportation. Walking, cycling, driving, or flying — it depends on distance (data size), terrain (data structure), and goal (insight needed). A bike won't cross an ocean; a plane is overkill for groceries. Match the tool to the task.
The Interactive Decision Tree
Follow this decision tree to find your chart type:
START: What's Your Main Question?
┌─────────────────────────────────────────────────────────────┐
│ WHAT DO YOU WANT TO SHOW? │
└─────────────────────────────────────────────────────────────┘
│
├──→ "Which category is biggest?" ────→ COMPARISON
│
├──→ "How did values change over time?" ────→ TREND
│
├──→ "What's the shape of the data?" ────→ DISTRIBUTION
│
├──→ "What are the parts of the whole?" ────→ COMPOSITION
│
├──→ "Are these two variables related?" ────→ RELATIONSHIP
│
└──→ "What's the geographic pattern?" ────→ GEOGRAPHIC
BRANCH 1: Comparison
"Which category is biggest / How do categories rank?"
How many categories?
├─→ 2-10 categories ────→ Vertical Bar Chart (sorted by value)
├─→ 10-25 categories ───→ Horizontal Bar Chart (sorted by value)
└─→ 25+ categories ─────→ Consider grouping or showing Top 10 + "Others"
Do you need to compare multiple metrics per category?
├─→ Yes (2-3 metrics) ──→ Grouped Bar Chart
├─→ Yes (4+ metrics) ───→ Small Multiples (separate charts)
└─→ No (single metric) ─→ Simple Bar Chart
Do you need to show both parts and total?
└─→ Yes ────────────────→ Stacked Bar Chart (100% for composition)
Example Charts:
- Simple Bar: "Revenue by Product Category"
- Grouped Bar: "Revenue and Profit by Product Category"
- Horizontal Bar: "Sales Across 20 Indian Cities"
BRANCH 2: Trend
"How did values change over time?"
Is time continuous or discrete?
├─→ Continuous (daily, weekly) ────→ Line Chart
└─→ Discrete (quarterly, yearly) ──→ Bar Chart or Line Chart
How many time series?
├─→ 1 series ──────────→ Single Line Chart
├─→ 2-5 series ────────→ Multi-Line Chart (use direct labeling)
├─→ 6+ series ─────────→ Small Multiples or Aggregate
└─→ Show composition ───→ Stacked Area Chart
Do you want to emphasize magnitude?
└─→ Yes (cumulative) ───→ Area Chart (filled under line)
Example Charts:
- Line Chart: "Daily Active Users — Jan to Jun 2025"
- Multi-Line: "Revenue by Region Over Time"
- Area Chart: "Cumulative Sign-ups Growth"
- Stacked Area: "Revenue by Product Line Over Quarters"
BRANCH 3: Distribution
"What's the shape / spread of the data?"
Single variable distribution:
├─→ Show frequency bins ───────→ Histogram
├─→ Show median & outliers ────→ Box Plot
└─→ Show full density curve ───→ Violin Plot / Density Plot
Compare distributions across groups:
├─→ 2-5 groups ────────────────→ Box Plots (side-by-side)
└─→ 6+ groups ─────────────────→ Violin Plots or Histograms (small multiples)
Example Charts:
- Histogram: "Age Distribution of Customers"
- Box Plot: "Order Value Distribution by City"
- Violin Plot: "Delivery Time Distribution Across Restaurants"
BRANCH 4: Composition
"What are the parts that make up the whole?"
How many parts?
├─→ 2-5 parts, simple story ───→ Pie Chart (sorted by size)
├─→ 2-5 parts, need comparison ─→ Stacked Bar Chart (easier to compare)
├─→ 6-10 parts ────────────────→ Stacked Bar Chart or Treemap
└─→ 10+ parts ─────────────────→ Treemap (hierarchical)
Do parts change over time?
└─→ Yes ────────────────────────→ Stacked Area Chart
Do you need to compare composition across categories?
└─→ Yes ────────────────────────→ 100% Stacked Bar Chart (normalized)
Example Charts:
- Pie Chart: "Market Share of Top 3 Food Delivery Apps"
- Stacked Bar: "Revenue Composition by Quarter"
- Treemap: "Website Traffic by Source → Medium → Campaign"
- 100% Stacked Bar: "Customer Segment Mix by Region (normalized)"
BRANCH 5: Relationship
"Are these two variables related / correlated?"
Two continuous variables:
├─→ Simple relationship ────────→ Scatter Plot
└─→ Add third variable ─────────→ Bubble Chart (size) or Color-coded Scatter
Show correlation strength:
└─→ Multiple variable pairs ────→ Correlation Heatmap
Show flow between categories:
└─→ Yes ────────────────────────→ Sankey Diagram
Example Charts:
- Scatter Plot: "Marketing Spend vs Revenue"
- Bubble Chart: "Price vs Rating (bubble size = review count)"
- Correlation Heatmap: "Feature Correlation Matrix"
- Sankey: "User Journey (Homepage → Product → Cart → Checkout)"
BRANCH 6: Geographic
"What's the spatial pattern?"
Do you have geographic boundaries data?
├─→ Yes (regions, states) ──────→ Choropleth Map (color by value)
└─→ No (just lat/long points) ──→ Point Map or Bubble Map
Is geography the main insight?
├─→ Yes ────────────────────────→ Use Map
└─→ No (just context) ───────────→ Consider bar chart sorted by region
Example Charts:
- Choropleth Map: "Sales Density by State in India"
- Bubble Map: "Store Locations (bubble size = revenue)"
- Point Map: "Customer Locations (heatmap overlay)"
⚠️ CheckpointQuiz error: Missing or invalid options array
Common Scenarios — Quick Reference
Business Dashboard Scenarios
| Scenario | Question Type | Best Chart | Why | |----------|--------------|------------|-----| | Monthly revenue tracking | Trend | Line Chart | Time series, continuous | | Top 10 products by sales | Comparison | Horizontal Bar | Many categories, sorted | | Market share (3 competitors) | Composition | Pie Chart or Bar | Simple part-to-whole | | Sales by region on map | Geographic | Choropleth Map | Spatial pattern | | Revenue vs Profit by quarter | Comparison (multi-metric) | Grouped Bar Chart | Two metrics, few time points | | Customer age distribution | Distribution | Histogram | Single variable shape | | Marketing ROI (actual vs target) | Comparison | Bullet Chart | Actual vs benchmark | | Conversion funnel dropoff | Composition (flow) | Funnel Chart or Sankey | Sequential process | | Daily orders (last 90 days) | Trend | Line Chart | Time series, show pattern | | Order value by city (25 cities) | Comparison | Horizontal Bar | Many categories |
Analytics Project Scenarios
| Scenario | Question Type | Best Chart | Why | |----------|--------------|------------|-----| | Feature correlation matrix | Relationship | Heatmap | Many variable pairs | | Outlier detection | Distribution | Box Plot | Shows median + outliers | | Customer segments (2D) | Relationship | Scatter Plot (colored by segment) | Two continuous vars + category | | A/B test results | Comparison | Grouped Bar (control vs variant) | Compare two groups | | Seasonal pattern detection | Trend | Line Chart with yearly overlay | Multiple time series | | Revenue waterfall (breakdown) | Composition | Waterfall Chart | Cumulative changes | | Churn rate by tenure | Relationship | Line Chart or Scatter | Continuous relationship | | Sales by product category & region | Composition | Stacked Bar or Treemap | Hierarchical part-to-whole |
Presentation Scenarios
| Audience | Preference | Recommendation | |----------|-----------|----------------| | Executives | High-level, fast insight | Single KPI + trend line, minimal detail | | Business stakeholders | Actionable patterns | Bar charts, line charts with annotations | | Technical teams | Statistical detail | Box plots, scatter plots, histograms with stats | | General public | Intuitive, minimal jargon | Simple bars, pies (for simple data), clear labels |
Chart Selector Tool
'use client';
import { useState } from 'react';
export default function ChartSelector() {
const [step, setStep] = useState(1);
const [selections, setSelections] = useState({});
const [recommendation, setRecommendation] = useState(null);
const questions = {
1: {
question: "What do you want to show?",
options: [
{ label: "Compare categories", value: "comparison", next: 2 },
{ label: "Show change over time", value: "trend", next: 3 },
{ label: "Show data distribution", value: "distribution", next: 4 },
{ label: "Show parts of a whole", value: "composition", next: 5 },
{ label: "Show relationship between variables", value: "relationship", next: 6 },
{ label: "Show geographic pattern", value: "geographic", next: 7 }
]
},
2: { // Comparison
question: "How many categories?",
options: [
{ label: "2-10 categories", value: "few", result: { chart: "Vertical Bar Chart", description: "Best for comparing few categories. Sort by value unless natural order exists (e.g., months).", example: "Revenue by Product Category (8 products)", code: "Use simple bar chart, sorted descending" } },
{ label: "10-25 categories", value: "medium", result: { chart: "Horizontal Bar Chart", description: "Horizontal bars handle many categories better — labels don't overlap and are easier to read.", example: "Sales Across 20 Cities", code: "Horizontal bar chart, sorted by value" } },
{ label: "Need to compare multiple metrics", value: "multi", result: { chart: "Grouped Bar Chart", description: "Shows 2-3 metrics side-by-side per category. Limit to 2-3 metrics max (more becomes unreadable).", example: "Revenue and Profit by Quarter", code: "Grouped bar chart with legend" } },
{ label: "Need to show parts + total", value: "stacked", result: { chart: "Stacked Bar Chart", description: "Shows composition AND allows comparison of totals across categories.", example: "Revenue by Region, broken down by Product Line", code: "Stacked bar chart (not 100%)" } }
]
},
3: { // Trend
question: "How many time series?",
options: [
{ label: "Single metric over time", value: "single", result: { chart: "Line Chart", description: "The standard for time series. Time on X-axis, metric on Y-axis. Add reference lines for context.", example: "Daily Active Users — Jan to Jun", code: "Single line with average reference line" } },
{ label: "2-5 metrics over time", value: "multi", result: { chart: "Multi-Line Chart", description: "Compare multiple trends. Use direct labeling (label lines, not legend). Max 5 lines before it becomes spaghetti.", example: "Revenue by Region Over Time", code: "Multiple lines with direct labels" } },
{ label: "Show composition over time", value: "composition", result: { chart: "Stacked Area Chart", description: "Shows both component trends AND total. Useful for revenue breakdown by product line.", example: "Revenue by Product Line (Q1-Q4)", code: "Stacked area chart with categories" } },
{ label: "Compare two time points", value: "slope", result: { chart: "Slope Chart", description: "Shows change from Point A to Point B. Great for before/after comparisons.", example: "Revenue by Region: Q1 2024 vs Q1 2025", code: "Slope chart connecting two time points" } }
]
},
4: { // Distribution
question: "Single variable or compare groups?",
options: [
{ label: "Single variable shape", value: "single", result: { chart: "Histogram", description: "Shows frequency distribution. Choose bin size carefully — too few bins lose detail, too many create noise.", example: "Customer Age Distribution", code: "Histogram with 15-20 bins" } },
{ label: "Compare distributions (2-5 groups)", value: "compare", result: { chart: "Box Plots (side-by-side)", description: "Shows median, quartiles, and outliers for each group. Great for comparing distributions.", example: "Order Value Distribution by City", code: "Box plots with groups on X-axis" } },
{ label: "Full distribution curve", value: "density", result: { chart: "Violin Plot or Density Plot", description: "Shows complete distribution shape (better than box plot for seeing bimodal/skewed data).", example: "Delivery Time Distribution Across Restaurants", code: "Violin plot or KDE" } }
]
},
5: { // Composition
question: "How many parts?",
options: [
{ label: "2-5 parts, simple message", value: "few", result: { chart: "Pie Chart", description: "Works ONLY for 2-5 categories with a clear dominant slice. Order slices by size. Avoid 3D.", example: "Market Share: Swiggy 45%, Zomato 35%, Others 20%", code: "Pie chart with 3 slices" } },
{ label: "5-10 parts or need precision", value: "medium", result: { chart: "Stacked Bar Chart", description: "Better than pie for comparison (length > angle). Shows exact values clearly.", example: "Revenue Composition by Quarter", code: "Stacked bar (not 100%) with values" } },
{ label: "10+ parts or hierarchical", value: "many", result: { chart: "Treemap", description: "Shows hierarchical part-to-whole. Box size = proportion. Works for many categories.", example: "Website Traffic by Source → Medium → Campaign", code: "Treemap with 2 levels" } },
{ label: "Composition across groups", value: "compare", result: { chart: "100% Stacked Bar Chart", description: "Normalizes each bar to 100% to compare composition (not absolute values).", example: "Customer Segment Mix by Region", code: "100% stacked bar chart" } }
]
},
6: { // Relationship
question: "What type of relationship?",
options: [
{ label: "Two continuous variables", value: "scatter", result: { chart: "Scatter Plot", description: "Shows correlation between X and Y. Add trendline to show direction. Use transparency if points overlap.", example: "Marketing Spend vs Revenue", code: "Scatter plot with trendline" } },
{ label: "Three variables (X, Y, size)", value: "bubble", result: { chart: "Bubble Chart", description: "Scatter plot + third variable as bubble size. Limit to 3 variables (more = unreadable).", example: "Price vs Rating (bubble = review count)", code: "Bubble chart with legend" } },
{ label: "Correlation matrix", value: "heatmap", result: { chart: "Correlation Heatmap", description: "Shows correlation coefficients for all variable pairs. Use diverging color scale (red-white-blue).", example: "Feature Correlation Matrix (8 variables)", code: "Heatmap with correlation coefficients" } },
{ label: "Flow between stages", value: "flow", result: { chart: "Sankey Diagram", description: "Shows flow/movement between categories. Width = volume. Good for user journeys, budget allocation.", example: "User Journey: Homepage → Product → Cart → Checkout", code: "Sankey diagram with flow widths" } }
]
},
7: { // Geographic
question: "What's your data structure?",
options: [
{ label: "Values by region/state", value: "regions", result: { chart: "Choropleth Map", description: "Color-code regions by value. Use sequential color scale (light to dark).", example: "Sales Density by State in India", code: "Filled map with color gradient" } },
{ label: "Point locations with values", value: "points", result: { chart: "Bubble Map", description: "Show locations as points, size = value. Good for store locations, customer density.", example: "Flipkart Warehouse Locations (bubble = capacity)", code: "Map with sized bubbles" } },
{ label: "Geography is just context", value: "context", result: { chart: "Bar Chart (sorted by region)", description: "If geography isn't the insight, use bar chart. Easier to compare values than on a map.", example: "Sales by State (bar chart)", code: "Horizontal bar chart, sorted" } }
]
}
};
const handleSelection = (option) => {
const newSelections = { ...selections, [step]: option.value };
setSelections(newSelections);
if (option.result) {
setRecommendation(option.result);
setStep('result');
} else if (option.next) {
setStep(option.next);
}
};
const reset = () => {
setStep(1);
setSelections({});
setRecommendation(null);
};
if (step === 'result' && recommendation) {
return (
<div className="max-w-3xl mx-auto p-8 bg-gradient-to-br from-teal-50 to-blue-50 rounded-xl border-2 border-teal-200">
<div className="text-center mb-6">
<div className="inline-flex items-center justify-center w-16 h-16 bg-teal-500 text-white rounded-full text-3xl mb-4">
📊
</div>
<h2 className="text-3xl font-bold text-gray-900 mb-2">
Recommended: {recommendation.chart}
</h2>
</div>
<div className="bg-white rounded-lg p-6 shadow-md mb-6">
<h3 className="font-semibold text-lg text-gray-900 mb-2">Why this chart?</h3>
<p className="text-gray-700 leading-relaxed mb-4">{recommendation.description}</p>
<h3 className="font-semibold text-lg text-gray-900 mb-2">Example use case:</h3>
<p className="text-teal-700 font-medium mb-4">"{recommendation.example}"</p>
<h3 className="font-semibold text-lg text-gray-900 mb-2">Implementation tip:</h3>
<code className="block bg-gray-100 p-3 rounded text-sm text-gray-800">
{recommendation.code}
</code>
</div>
<button
onClick={reset}
className="w-full py-3 px-6 bg-teal-600 hover:bg-teal-700 text-white font-semibold rounded-lg transition-colors"
>
Choose Another Chart
</button>
</div>
);
}
const currentQuestion = questions[step];
return (
<div className="max-w-3xl mx-auto p-8 bg-white rounded-xl border-2 border-gray-200">
<div className="mb-8">
<div className="flex items-center justify-between mb-4">
<span className="text-sm font-semibold text-teal-600">
Step {step} of {Object.keys(questions).length}
</span>
{step > 1 && (
<button
onClick={reset}
className="text-sm text-gray-600 hover:text-gray-900 underline"
>
Start Over
</button>
)}
</div>
<h2 className="text-2xl font-bold text-gray-900">
{currentQuestion.question}
</h2>
</div>
<div className="space-y-3">
{currentQuestion.options.map((option, index) => (
<button
key={index}
onClick={() => handleSelection(option)}
className="w-full text-left p-4 rounded-lg border-2 border-gray-200 hover:border-teal-500 hover:bg-teal-50 transition-all group"
>
<span className="text-lg font-medium text-gray-900 group-hover:text-teal-700">
{option.label}
</span>
</button>
))}
</div>
</div>
);
}To use this tool: Copy the component above into your project, or follow the decision tree manually to find your chart type.
Pro Tip: The tool gives you the right chart TYPE, but effectiveness also depends on good design (clear labels, sorted data, appropriate colors, annotations). Use this tool + visualization principles together.
When to Break the Rules
Sometimes the "correct" chart isn't the best choice. Here's when to consider alternatives:
Scenario 1: Pie Chart vs Bar Chart
Rule: "Use pie charts for 2-5 simple parts" Alternative: Bar chart is ALWAYS better for comparison
When to use pie: Your audience expects it (market share), data is truly simple (2-3 dominant categories), message is "A dominates B and C"
When to use bar instead: You need precise comparison, you have 4+ categories, or any slice is < 5% (invisible in pie)
Scenario 2: Dual-Axis Charts
Rule: "Avoid dual Y-axes (misleading scales)" Alternative: Sometimes two metrics need to be on one chart
When it's acceptable:
- Two metrics share same trend but different magnitudes (revenue ₹10M, orders 50K)
- Clearly labeled with units on both sides
- Same scale type (both linear, both log)
- Not trying to "prove" correlation (just showing parallel trends)
Better alternative: Small multiples (two charts stacked, same X-axis)
Scenario 3: 3D Charts
Rule: "Never use 3D charts" Alternative: None. Seriously, never use 3D charts. Not even once.
Scenario 4: Tables vs Charts
Rule: "Visualize data, don't use tables" When tables are better:
- Audience needs exact values (financial reporting)
- Few data points (2×3 table is clearer than chart)
- Multiple metrics per category (chart would need grouping)
- Data is for lookup, not pattern-finding
Hybrid approach: Table with embedded sparklines (mini charts in cells)
Scenario 5: Truncated Y-Axis
Rule: "Bar charts must start at zero" When to break it: Never for bar charts. But for line charts:
- When baseline is stable and irrelevant (stock prices ₹850-900)
- When small changes in large baseline matter (temperature 98°F vs 101°F)
- When you CLEARLY label truncation with break symbol (⚡)
Better approach: Use bullet chart or show difference from baseline
⚠️ FinalQuiz error: Missing or invalid questions array
⚠️ SummarySection error: Missing or invalid items array
Received: {"hasItems":false,"isArray":false}