Module 8: Data visualization and storytelling
View study sheet (PDF) View SQL cheat sheet (PDF)
This session teaches students to turn market data into a figure that tells the truth, and to recognize when a figure does not. Auction and resale pricing data can be summarized many ways: a pricing power ratio, a sell-through rate, a count of sold lots by quarter, and each of those summaries can be charted honestly or dishonestly with the same underlying numbers. Students use the sandbox's pre-built charts and export tools to build two figures, a bar chart comparing pricing power across brands and a line chart of sold-lot counts over time, and then practice the editorial judgment that separates a chart that informs from one that misleads: choosing the right chart type for the question, deciding where an axis should start, and deciding which window of time is fair to show. The session closes on a caution that runs through the rest of the course, that the newest quarters in this dataset are still being ingested, and a line chart that lets that under-ingestion masquerade as a market decline is a dishonest chart regardless of how the axis is drawn.
Target course(s) and level
Data visualization, business communication, or data journalism course. Suitable for undergraduates and graduate students in business, communications, or design programs. No finance background is assumed, and no prior charting tool is required beyond what the sandbox provides.
Learning objectives
By the end of this session, students will be able to:
- Select an appropriate chart type for a given market data question, distinguishing when a bar chart, a line chart, or a table best serves the reader.
- Build a pricing power comparison chart and a sold-lot-count time series using the sandbox's pre-built charts and export tools, without writing code.
- Identify axis truncation and cherry-picked time windows as two common techniques that make a chart misleading without altering the underlying numbers.
- Explain why a time series ending in the most recent quarter requires a caveat about ongoing data ingestion, and revise a chart's title or footnote to state that caveat plainly.
- Critique a chart built by a classmate against a short honesty checklist covering axis choice, time window, and labeling.
- (Extension) Export a query result via the production API and reproduce one of the two chart types in a Python plotting library.
Prerequisites
An introductory course in business communication, statistics, or design, or general interest in how data is presented to an audience. No prior exposure to SQL or the sandbox is assumed. The optional code extension assumes basic Python familiarity.
Materials and access needed
- Sandbox access at sandbox.altfndata.com, self-registered with a work or school email, auto-approved.
- Projector or screen share for the instructor demo.
- The coverage browser tab, used before the demo to confirm how the chosen brands appear in the designer field.
- A one-page honesty checklist (axis choice, time window, labeling, and caveat language), distributed at the start of the session or written on the board during the discussion.
- For the optional extension only: an instructor class API key requested from info@altfndata.com, and the downloadable Python client (altfndata_client.py) or tutorials notebook (altfndata_tutorials.ipynb) at docs.altfndata.com.
Session outline (90 minutes)
- 0 to 15 min: Introduce the session's premise, that the same numbers can produce an honest or a dishonest chart, and preview the two figures the class will build.
- 15 to 25 min: Sandbox orientation. Confirm students can open a data table, run a query, and reach the pre-built charts and export tabs.
- 25 to 45 min: Guided demo, build a pricing power comparison bar chart across a handful of brands.
- 45 to 60 min: Guided demo, build a sold-lot-count line chart by quarter for a single category, and walk through the recency caveat as a visualization problem, not just a data problem.
- 60 to 75 min: Small-group exercise, each group builds one chart, then deliberately produces a misleading version of the same chart using truncation or a cherry-picked window, and prepares to explain the trick.
- 75 to 85 min: Class discussion, groups present their honest and misleading pairs and the class applies the honesty checklist.
- 85 to 90 min: Wrap-up and homework assignment.
In-class demo (sandbox-first, no code)
- Open sandbox.altfndata.com, sign in, and select the handbags data table (or another category the instructor prefers) from the SQL editor dropdown.
- Open the coverage browser tab and confirm how two or three well-known brands are written in the designer field before filtering.
- Return to the SQL editor and run the first guided query below, which computes pricing power for a small set of brands.
- Open the pre-built charts tab and render the result as a bar chart. Ask students what chart type would have served the same data poorly, for example a line chart implying a trend across brands that have no natural order.
- Run the second guided query, sold-lot count by quarter for a single category, and render it as a line chart.
- Point to the final one or two quarters on the chart and ask students what they notice about the shape of the line there. Introduce the recency caveat directly: the newest quarters are still being ingested, so a downturn at the very end of the line is very likely an ingestion artifact, not a demand signal, and a chart that omits this caveat misleads its reader even though every number in it is correct.
- Demonstrate a truncated axis on the bar chart from step 4, starting the y-axis well above zero, and discuss how it exaggerates small differences between brands.
- Export both charts and the underlying result sets, and show students where the export lives for use in the small-group exercise and the homework assignment.
Datasets and queries used
Dataset: handbags data (documented fields: designer, model, item_title, sale_date, usd_price_decimal, sale_estimates_high_usd_price, status, vendor, stock_ticker).
Query 1, pricing power comparison across brands, for a bar chart:
SELECT designer,
approx_percentile(usd_price_decimal / sale_estimates_high_usd_price, 0.5) AS pricing_power,
COUNT(*) AS sold_lots
FROM all_handbags_data
WHERE status = 'sold'
AND sale_estimates_high_usd_price > 0
AND designer IN ('Hermès', 'Chanel', 'Louis Vuitton')
GROUP BY designer
ORDER BY pricing_power DESC;
Query 2, sold-lot count by quarter, for a line chart:
SELECT date_trunc('quarter', CAST(sale_date AS date)) AS sale_quarter,
COUNT(*) AS sold_lots
FROM all_handbags_data
WHERE status = 'sold'
GROUP BY date_trunc('quarter', CAST(sale_date AS date))
ORDER BY sale_quarter;
Optional API extension, equivalent request body to query 1, exported for a Python plotting library (POST /v1/tables/all_handbags_data/query, header X-API-Key):
{
"fields": ["designer", "usd_price_decimal", "sale_estimates_high_usd_price"],
"filters": [
{"field": "status", "op": "eq", "value": "sold"},
{"field": "sale_estimates_high_usd_price", "op": "gt", "value": 0},
{"field": "designer", "op": "in", "value": ["Hermès", "Chanel", "Louis Vuitton"]}
],
"limit": 1000
}
Discussion questions
- What makes a bar chart the right choice for comparing pricing power across brands, and what would be lost or distorted by showing the same comparison as a line chart?
- When does truncating a y-axis serve the reader by making a real difference visible, and when does it cross into misleading exaggeration? Where is the line?
- A line chart of sold-lot count dips in its final quarter because of ingestion lag, not falling demand. What obligation does the chart's creator have to the reader in that situation?
- How would you design a caveat or footnote so that a reader who only glances at the chart still absorbs the recency warning?
- What is the difference between choosing a favorable time window because it is genuinely the most relevant period, and cherry-picking a window because it tells a better story?
- Who is harmed when a chart built from accurate numbers still leads its reader to a false conclusion, and does it matter whether the distortion was intentional?
- If you were reviewing a colleague's chart before it went into a client report, what three questions would you ask first?
Homework assignment
Each student selects one category table and one comparison question (for example, pricing power across three brands, or sell-through across two auction houses, or sold-lot count over time for a single brand), and produces two charts from the same underlying query: one built to inform as honestly as possible, and one built to mislead using a specific, named technique such as axis truncation or a cherry-picked window. The submission is a short memo, no more than two pages, that includes both charts, the SQL query used, and a paragraph explaining exactly how the misleading version distorts the reader's takeaway and what an honest caption or footnote would need to say to correct it, including the recency caveat if the chart involves a time series. Grading criteria: correct chart-type choice for the honest version (25 percent), a clearly identifiable and well-explained distortion technique in the misleading version (30 percent), quality of the written critique connecting the two (30 percent), and clarity and professionalism of the memo (15 percent).
Going deeper
Key terms
- Pricing power: the median of realized price over high estimate for sold lots, a demand signal above or below 1.0.
- Sell-through: the share of offered lots, sold and unsold combined, that found a buyer.
- Axis truncation: starting a numeric axis above zero to exaggerate the apparent size of a difference.
- Cherry-picked window: selecting a start and end date for a time series specifically because it supports a preferred conclusion.
- Recency under-ingestion: the newest quarters in the dataset have fewer records because ingestion is still catching up, not because activity fell.
- Data-ink ratio: the design principle that a chart should devote as much of its visual weight as possible to the data itself, not decoration.
- Small multiples: a series of similar small charts, one per category, used to compare many groups without cluttering a single chart.
- Caption honesty: the practice of writing a chart's title or footnote so that a reader who reads only that text still reaches an accurate conclusion.
Common pitfalls
- Charting a quarterly time series all the way to the current quarter without noting the recency caveat, letting an ingestion artifact read as a demand decline.
- Choosing a line chart for a comparison across categories that have no natural order, implying a trend where none exists.
- Truncating an axis without disclosure, which can turn a small, unremarkable difference into what looks like a dramatic gap.
- Misspelling or mistyping a brand or house name in a filter (for example, missing an accent), which silently drops matching rows and produces an undercount that then gets charted as if it were complete.
- Including unsold lots in a pricing power calculation, which pulls the ratio down since unsold lots have no realized price to compare against the estimate.
- Presenting a single quarter's total as a definitive figure rather than checking it against neighboring quarters for consistency.
Additional queries to explore
-- Sell-through by house, to chart as a ranked bar chart
SELECT vendor,
COUNT(*) FILTER (WHERE status = 'sold') * 1.0 / COUNT(*) AS sell_through
FROM all_handbags_data
GROUP BY vendor
HAVING COUNT(*) >= 200
ORDER BY sell_through DESC
LIMIT 20;
-- Median realized price by quarter for one brand, a second time series option
SELECT date_trunc('quarter', CAST(sale_date AS date)) AS sale_quarter,
approx_percentile(usd_price_decimal, 0.5) AS median_price_usd
FROM all_handbags_data
WHERE status = 'sold'
AND designer LIKE '%Herm%'
GROUP BY date_trunc('quarter', CAST(sale_date AS date))
ORDER BY sale_quarter;
-- Distribution of pricing power across many brands at once, for a small-multiples exercise
SELECT designer,
approx_percentile(usd_price_decimal / sale_estimates_high_usd_price, 0.5) AS pricing_power,
COUNT(*) AS sold_lots
FROM all_handbags_data
WHERE status = 'sold'
AND sale_estimates_high_usd_price > 0
GROUP BY designer
HAVING COUNT(*) >= 100
ORDER BY pricing_power DESC
LIMIT 30;
Extension activities
- Take a chart built earlier in the course, such as the league table from the art business module, and redesign it as a small-multiples layout, one panel per house or brand, and evaluate whether the redesign clarifies or clutters the comparison.
- Recreate one of the session's two charts in a Python plotting library using data exported through the optional API extension, and compare the design defaults of the library against the sandbox's pre-built chart on the same honesty checklist.
- Collect three real charts from published market commentary or news coverage of the luxury or collectibles trade, and apply the honesty checklist to each, noting which techniques from this session appear.
Connections to other modules
This module draws its two example metrics, pricing power and sell-through, directly from Module 7, the business of the art market, and gives students the visualization skills to present those same figures responsibly. It sets up Module 10, time series and market indices, where the recency caveat becomes central to an entire quarterly index rather than a single chart. It also complements Module 2, data science and SQL, since every chart in this session begins with a query written in that module's vocabulary.