import numpy as np
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sb
pd.options.display.max_columns = 1008 Writing for an Audience
The previous chapters in this part taught you to visualize distributions with histograms and compare them across categories with catplots. But a chart does not speak for itself. Every visualization is created for someone, and the choices you make — what to include, what to exclude, how to frame the finding, how much detail to provide — should be driven by who that someone is.
This chapter explores audience analysis: the practice of understanding your reader before you write. Knowing your audience changes every aspect of your data communication, from the chart type you choose to the vocabulary you use to the narrative structure you follow. We will use the DIA passenger and House expenditure data from earlier chapters to illustrate how the same underlying analysis produces very different outputs depending on the intended audience.
8.1 Setup
8.2 Who Is Your Audience?
Andrew Abela, in Advanced Presentations by Design, argues that every data presentation should begin with three questions about the audience.
8.2.1 What does the audience already know?
A data scientist reviewing your work understands what a p-value means and expects to see one. A city council member may not know what a p-value is and would be better served by a plain-language statement like “This difference is very unlikely to be due to chance.” A general reader of a blog post falls somewhere in between and might benefit from a brief definition.
The level of existing knowledge determines your vocabulary, the amount of methodological detail you include, and how much context you need to provide for each chart.
8.2.2 What does the audience need to decide?
Data communication is rarely just informational — it almost always supports a decision. A DIA executive might need to decide whether to open a new terminal. A journalist might need to decide whether the passenger recovery trend is newsworthy. A congressional staffer might need to decide whether to recommend changes to an office’s spending practices.
The decision shapes what data matters. The executive cares about long-term capacity projections. The journalist cares about the narrative arc of decline and recovery. The staffer cares about line-item comparisons to peer offices. The same underlying dataset serves all three, but the analysis and presentation differ substantially.
8.2.3 What is the audience’s prior belief?
If your audience already believes that COVID-19 devastated air travel, a chart confirming that belief is unremarkable. The more interesting and useful contribution might be how quickly traffic recovered, or which airlines recovered fastest, or how DIA compared to other airports.
Understanding your audience’s priors helps you focus on what is genuinely new and useful rather than restating the obvious. Conversely, if your finding contradicts a widely held belief, you need to present stronger evidence and anticipate skepticism.
8.3 Getting to the Core
Sejal Vora, in The Power of Data Storytelling, argues that you should be able to state your core finding in a single sentence before you create any visualization. This sentence becomes the organizing principle for everything else.
Consider the House expenditure data from Chapter 7. Several possible core findings emerge from the same data, and each would lead to a different presentation.
- “Democratic and Republican offices spend similar amounts overall, but differ meaningfully in how they allocate across categories.”
- “Members representing distant districts spend significantly more on travel than those near Washington, D.C.”
- “Incumbent members spend 12% more than freshmen, regardless of party.”
Each of these core findings would produce a different chart, a different headline, and a different narrative structure. Before opening matplotlib, decide which story you are telling.
8.4 Tailoring a Visualization
Let’s demonstrate with the DIA passenger data.
passenger_df = pd.read_csv('passengers.csv')
passenger_df['Month'] = pd.to_datetime(passenger_df['Month'])
passenger_df.set_index('Month', inplace=True)
passenger_df.drop(columns=['Cargo'], inplace=True)8.4.1 For a technical audience
A data science team reviewing your analysis wants to see the full data, clear methodology, and reproducible code. You might produce a detailed time series with multiple airlines, consistent axis scales, and statistical annotations.
f, ax = plt.subplots(figsize=(14, 6))
for airline in ['United', 'Southwest', 'Frontier']:
passenger_df[airline].plot(ax=ax, label=airline, alpha=0.8)
ax.set_ylabel('Monthly Passengers')
ax.set_xlabel('Date')
ax.set_title('DIA Monthly Passengers by Major Carrier, 1995–2021')
ax.legend()
ax.axvline(pd.Timestamp('2020-03-01'), color='gray', linestyle='--', alpha=0.5)This chart is detailed and precise. It includes multiple series, uses consistent colors, and annotates the COVID-19 onset without editorial commentary. A technical audience would know to examine the relative recovery rates and the crossover between United and Southwest around 2010.
8.4.2 For a general audience
A blog post reader wants a clear takeaway, minimal jargon, and a chart that communicates the point at a glance. Simplify to a single line (total passengers) with prominent annotations and a descriptive title.
f, ax = plt.subplots(figsize=(12, 5))
passenger_df['Grand'].plot(ax=ax, color='steelblue', linewidth=2)
ax.annotate(
'COVID-19\nshutdowns',
xy=(pd.Timestamp('2020-04-01'), 500_000),
fontsize=12,
fontweight='bold',
color='crimson'
)
ax.set_ylabel('Monthly Passengers', fontsize=12)
ax.set_title('How COVID-19 Crushed Denver Airport Traffic', fontsize=14)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_xlabel('')The title is a finding, not a description. The y-axis is labeled with a plain-English phrase. The top and right spines are removed to reduce clutter. There is one annotation pointing to the key moment. A general reader can absorb the message in three seconds.
8.4.3 For a decision-maker
An airport executive needs to decide whether passenger traffic has recovered enough to justify expansion. The most useful chart is a comparison of current levels against a pre-pandemic baseline.
f, ax = plt.subplots(figsize=(12, 5))
# Compute a pre-pandemic baseline: average monthly traffic 2015-2019
baseline = passenger_df.loc['2015':'2019'].groupby(passenger_df.loc['2015':'2019'].index.month).mean()
# Plot 2021 actual vs. baseline
actual_2021 = passenger_df.loc['2021', 'Grand']
ax.plot(range(1, 13), baseline['Grand'].values, label='2015–2019 Average',
color='gray', linestyle='--', linewidth=2)
ax.plot(actual_2021.index.month, actual_2021.values, label='2021 Actual',
color='steelblue', linewidth=2, marker='o')
ax.set_xticks(range(1, 13))
ax.set_xticklabels(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])
ax.set_ylabel('Monthly Passengers')
ax.set_title('2021 Recovery vs. Pre-Pandemic Baseline')
ax.legend()The same data, the same underlying truth, but three very different presentations optimized for three very different readers.
8.5 Narrative Structure
Data stories, like all stories, have a structure. Research by Segel and Heer, and later discussed by Bach, Stefaner, and others in Data-Driven Storytelling, identified common narrative patterns.
8.5.1 The Martini Glass
This pattern begins with a narrow, author-driven narrative (“here is the finding”) and then opens up to let the reader explore the data on their own. A blog post that leads with a chart and headline, then provides an interactive dashboard, follows this pattern. It works well for general audiences who benefit from being told the conclusion before they examine the evidence.
8.5.2 The Interactive Slideshow
This pattern alternates between author-driven slides and reader-driven exploration at each step. A scrollytelling article where the reader advances through annotated charts is the classic example. It works well for audiences who want to understand the methodology step by step.
8.5.3 The Drill-Down
This pattern starts with an overview and progressively reveals more detail. You might begin with total DIA traffic, then break down by airline, then by route, then by day of week. It works well for analytical audiences who want to explore the data at multiple levels.
Your choice of structure depends on the audience’s level of engagement and expertise. A general audience benefits from the Martini Glass (give them the conclusion first). A technical audience may prefer a drill-down (let them evaluate the methodology).
8.6 Communicating Data to an Audience
Drawing from Drucker, Huron, Kosara, Schwabish, and Diakopoulos in Data-Driven Storytelling, several principles guide effective data communication regardless of audience.
Annotation is argument. When you add an annotation to a chart — a label, an arrow, a highlighted region — you are making an argument about what the reader should pay attention to. Use annotations deliberately to guide the reader’s eye to the most important patterns.
Redundancy builds comprehension. Encoding the same information in multiple channels (color and label, position and size) makes the chart accessible to readers with different cognitive styles and to those with color vision deficiencies.
Simplicity is not dumbing down. Removing unnecessary gridlines, decimals, or chart elements does not make your analysis less rigorous. It makes it more communicable. Einstein reportedly said “Everything should be made as simple as possible, but not simpler.” The same applies to charts.
8.7 Writing the First Draft
When you sit down to write about your data analysis, drawing from Nolan and Stoudt’s Communicating with Data:
Start with the finding. Your opening sentence should state the most important result. “DIA passenger traffic fell 93% between February and April 2020” is a finding. “We analyzed monthly passenger data from 1995 to 2021” is a methodology statement — useful, but secondary.
Use concrete numbers. Vague claims (“traffic dropped significantly”) are less compelling and less trustworthy than specific ones (“traffic dropped from 5.3 million to 380,000 passengers”).
Explain, don’t just show. A chart alone is not an argument. Tell the reader what the chart shows, why it matters, and what it means for the question at hand. Resist the temptation to let the chart “speak for itself.”
Anticipate objections. A sophisticated reader will wonder about seasonal effects, population growth, or airline mergers. Address these proactively — even briefly — to build credibility. If you don’t raise the obvious objections, the reader will assume you did not consider them.
8.8 Exercises
Choose a finding from the House expenditure data in Chapter 7. Create two versions of a chart communicating that finding: one for a congressional staffer who works with this data daily, and one for a constituent reading a local newspaper. Write a one-paragraph caption for each.
Solution:
For the staffer, include party breakdown, confidence intervals, dollar amounts, and a note about the data source and quarter. The caption might read: “Average Q3 2021 office spending by party (N=218 D, 212 R). Error bars show 95% CI. Source: ProPublica disbursement data.”
For the constituent, simplify to a single comparison with plain language. The caption might read: “Your representative’s office spent $387,000 last quarter, compared to the average of $340,000 across all congressional offices. Most of this spending went to staff salaries and office rent.”
Take any analysis you have done so far in this book (loading Census data, aggregating CDC mortality data, visualizing weather distributions). Write a three-sentence summary that leads with the finding, provides one supporting number, and briefly notes a caveat.
Solution:
Example: “Heart disease deaths in the U.S. increased 5.4% from 2019 to 2020, the largest year-over-year jump in the past decade. Total deaths rose from approximately 657,000 to 692,000, a change that coincides with the onset of the COVID-19 pandemic. This increase likely reflects both direct cardiovascular effects of COVID-19 and disruptions to routine cardiac care, though the CDC data does not distinguish between these mechanisms.”
Identify three different audiences for the county-level COVID data you will encounter in Chapter 12 (e.g., a public health official, a journalist, a concerned citizen). For each, write one sentence describing what they already know, what they need to decide, and what chart type would serve them best.
Solution:
A public health official knows epidemiological terminology and needs to decide where to allocate resources. A choropleth map of per-capita case rates, colored by severity thresholds, would serve them best because it shows geographic hotspots at a glance.
A journalist knows the broad pandemic narrative and needs to decide whether a local angle is newsworthy. A comparative bar chart showing the local county against state and national averages would work because it immediately establishes whether the local situation is typical or exceptional.
A concerned citizen has limited statistical background and needs to decide whether to change personal behavior. A simple line chart of local weekly trends with a plain-language annotation (“cases rising” or “cases stable”) and no jargon would be most effective.
You have been asked to create a data story about congressional spending for a class blog. Describe how the story would differ if you used the Martini Glass structure versus the Drill-Down structure. Which would you choose for your classmates? Why?
Solution:
The Martini Glass would begin with the headline finding (“Congressional offices spend an average of $340,000 per quarter, but the range is enormous”) and a single chart, then offer an interactive table or dashboard where readers can look up their own representative. This works well for classmates who may not read past the first paragraph.
The Drill-Down would start with total spending, then break down by party, then by spending category, then highlight a few interesting outliers. This builds understanding progressively but requires the reader to stay engaged through multiple charts. For classmates in a data science course, the drill-down may be more appropriate because the audience is learning analytical techniques, not just consuming findings.
Take the DIA passenger chart and encode the same information in at least two visual channels (e.g., both color and a text annotation, or both line thickness and a legend label). How does the redundancy affect readability?
Solution:
f, ax = plt.subplots(figsize=(12, 5))
passenger_df['Grand'].plot(ax=ax, color='steelblue', linewidth=2)
# Redundancy: both a vertical line AND a text annotation for the same event
ax.axvline(pd.Timestamp('2020-03-01'), color='crimson', linestyle='--',
linewidth=1.5, label='COVID-19 Onset')
ax.annotate('COVID-19\nOnset', xy=(pd.Timestamp('2020-03-01'), 5_000_000),
fontsize=10, color='crimson', fontweight='bold')
ax.legend()
ax.set_ylabel('Monthly Passengers')
ax.set_title('DIA Passenger Traffic')The redundancy ensures that a reader who misses the vertical line will still see the annotation, and vice versa. This is especially helpful when charts are printed in black and white or viewed by readers with color vision deficiencies.
8.9 Looking Ahead
You now have a framework for thinking about audience that will inform every visualization and data narrative you produce. In Chapter 9, we shift to a new data type — temporal data — and the unique challenges of working with dates, times, and timestamps in Python.