DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
01
Introduction to Matplotlib
02
Line, Bar, and Scatter Plots in Matplotlib
03
Introduction to Seaborn for Statistical Plots
04
Heatmaps, Pair Plots, and Distribution Plots in Seaborn
05
Interactive Visualizations with Plotly
06
Building Dashboards with Streamlit (Python-Only)
07
Data Storytelling: Choosing the Right Chart

Data Storytelling: Choosing the Right Chart

This closes out the visualization arc of this series. data storytelling chart selection isn't an aesthetic decision — it's a communication decision, and getting it wrong doesn't just look unpolished, it actively misleads. This article works through a goal-first framework for choosing the right chart type, ties each chart type back to the Python libraries covered earlier in this series, and closes with the subtraction principle for cleaning up whatever chart you've chosen.

Chart Selection Is a Communication Decision, Not an Aesthetic One

The core reframe worth leading with

Choosing a chart type because it looks most sophisticated, rather than because it most directly communicates the specific relationship or trend actually present in the data, is one of the most common mistakes in data storytelling. A 3D pie chart with a dramatic rotation might look impressive in a slide deck — but if the underlying question is "how did sales change over the last twelve months," it answers a completely different question than the one actually being asked.

Why this matters beyond looking unpolished

This is worth stating precisely: the wrong chart format doesn't just look incorrect — it actively misleads. A genuinely different, more serious risk than a chart that's merely unattractive. A pie chart with too many slices makes it genuinely difficult to compare two similarly-sized categories accurately, since human perception is considerably worse at comparing angles and areas than at comparing bar lengths or positions along a shared axis. A truncated y-axis on a bar chart can make a trivial difference look dramatic. These aren't cosmetic flaws — they're the chart actively communicating something false about the underlying data.

What this article covers

A goal-first framework for chart selection — comparison, trend, proportion, relationship, distribution — tying each chart type directly back to the Python libraries (Matplotlib, Seaborn, Plotly, Streamlit) covered throughout the earlier articles in this series, and closing with the "subtraction" principle for cleaning up a chart once its type has genuinely been chosen correctly.

Start with the Goal, Not the Data

The question to ask before opening any plotting library

Before writing a single line of px. or ax. code: are you comparing values across categories? Showing a trend over time? Highlighting a proportion of some whole? Exploring a relationship between two variables? The goal determines the chart type — not the data alone. The exact same dataset can support several genuinely different, equally valid charts, depending entirely on which specific question you're trying to answer with it.

A quick reference worth centering the whole article around
  • Comparing categories → bar chart

  • Showing change over time → line chart

  • Showing parts of a whole → pie or donut chart, used sparingly

  • Exploring correlation between two numeric variables → scatter plot

This four-line mapping is genuinely worth internalizing before anything more nuanced — it resolves the majority of everyday chart-selection decisions immediately, without needing to think much further.

Why bar charts are the safest default when genuinely unsure

Worth stating explicitly, as the practical "when in doubt" fallback: bar charts are versatile, universally understood, and rarely mislead, since the human brain is genuinely excellent at comparing bar lengths at a glance — a well-established finding in data visualization research, and part of why bar charts remain the safest general-purpose default whenever you're not entirely sure which chart type actually fits a given question best.

Matching Chart Type to Question: A Practical Walkthrough

Trend questions

Tracking growth, decline, or volatility across days, months, or years calls for a line chart — it shows a dataset's journey clearly, since the connecting line directly represents the passage of ordered time, exactly the reasoning covered in the earlier Matplotlib and Seaborn line-plot articles. A multi-line variant is genuinely useful when comparing several related series over the same time period — sales versus profit, for instance — letting a viewer track both trajectories, and how they diverge or converge, in a single glance.

What goes wrong with the wrong choice: using a bar chart for a long time series (say, daily data across an entire year) buries the actual trend under 365 individual bars, none of which clearly conveys the overall trajectory the way a single connected line would.

Relationship questions

"Does ad spend correlate with conversions?" "Does order size relate to delivery time?" These call for a scatter plot — tying directly back to the earlier scatter-plot article — since each individual dot represents one data point, letting clusters, outliers, and correlations surface immediately and directly, in a way no other chart type shows quite as clearly.

What goes wrong with the wrong choice: forcing this same question into a line chart implies a false sense of ordered sequence between points that may not actually exist, and a bar chart can't represent two continuous numeric variables against each other at all — it's built for categorical comparison, not point-level relationships.

Distribution and correlation-across-many-variables questions

For understanding a single variable's shape, histograms and KDE plots — tying back to the earlier Seaborn distribution article — are the right tool. For surveying correlation across many numeric columns simultaneously, a heatmap — tying back to the earlier Seaborn heatmap article — condenses what would otherwise require dozens of individual scatter plots into one readable, color-coded matrix.

What goes wrong with the wrong choice: trying to convey a distribution's shape with a single summary bar (just the mean, say) discards genuinely important information — a bimodal distribution and a normal one can share the exact same mean while looking nothing alike, and a bar chart showing only that shared mean would make them appear identical when they genuinely aren't.

Chart Choice for Dashboards vs. One-Off Reports

The distinction worth making explicit

The right chart choice genuinely differs by context, and it's worth being deliberate about which context you're actually designing for. Real-time or frequently-refreshed dashboards benefit from simple visuals — line charts, grouped bar charts, single-number indicators — that are quick to read at a glance, since a dashboard viewer typically has seconds, not minutes, to absorb what they're looking at. Overly complex visuals, especially 3D charts, actively make it harder to spot what matters in exactly this fast-glance context, since the added visual complexity demands more careful, slower interpretation than a dashboard setting typically allows for.

Static, presentation-style reports have more room

A static report or presentation slide has more room for a richer, more deliberately composed chart — an annotated line chart highlighting one specific inflection point, for instance — since the audience genuinely has time to study a single, carefully-composed visual, rather than scan a live, constantly-updating dashboard at a glance.

Tying this back to the tools covered earlier in this series

Streamlit and Plotly dashboards, covered in the earlier articles in this series, should lean toward the "dashboard" side of this distinction: simple, fast-reading charts, generously using use_cTrue and consistent color palettes, exactly the guidance given in the earlier Streamlit article. A Matplotlib or Seaborn figure destined for a written report or a slide presentation, by contrast, can genuinely afford more nuance, more careful annotation, and more deliberate, one-time composition — the extra control Matplotlib and Seaborn offer over Plotly's more interactivity-focused defaults is precisely what a static, presentation-quality figure benefits from.

The Subtraction Principle: Cleaning Up Once the Type Is Chosen

The data-ink ratio principle

Worth closing on directly: every element of a chart should either show data or add essential context. Everything else — unnecessary gridlines, a redundant legend repeating information already obvious from the chart itself, decorative color variation that doesn't actually encode any additional meaning — is genuinely noise, actively competing with the actual insight for the viewer's limited attention.

A practical process for applying this

Once the right chart type has genuinely been chosen — following the goal-first framework covered in Sections 2 and 3 — deliberately look at every remaining element: titles, axis labels, annotations, gridlines, color choices. For each one, ask directly: does this element genuinely support comprehension, or does it just add visual clutter? A chart title restating something already obvious from the axis labels can go. A legend for a chart with only one data series (where color carries no actual distinguishing information at all) can go. Gridlines dense enough to compete visually with the actual data points themselves should be lightened, or removed entirely.

# Before: default Matplotlib styling, genuinely fine but not deliberately minimal
fig, ax = plt.subplots()
ax.plot(x, y)
ax.grid(True)

# After: deliberately reduced to just what supports comprehension
fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.grid(True, alpha=0.3)   # present, but genuinely subtle rather than competing with the data

This kind of small, deliberate subtraction — removing the top and right chart borders, lightening (rather than fully removing) gridlines — is exactly the kind of judgment call the subtraction principle is asking you to make consistently, element by element, once the underlying chart type itself is already correct.

Closing framing, tying the whole visualization series together

The most effective data stories are defined by deliberate subtraction, not addition. Every technical skill covered throughout this series — Matplotlib's fine-grained Figure/Axes control, Seaborn's fast statistical defaults, Plotly's interactivity, Streamlit's dashboard framework — is genuinely only as effective as the judgment applied in choosing exactly what actually belongs on the final chart, and exactly what doesn't. Knowing how to build any chart type this series has covered is the mechanical half of the skill; knowing which one to build, and what to leave off it once you have, is the genuinely harder, more valuable half — and it's the one this article has focused on directly.

PREVIOUS