1. Courses
  2. Data
  3. Statistics for Data Work
  4. Stop 1

35 minIntermediate

Describing data honestly

Before any test or model, someone asks "what does a typical order look like?", and the first number you give shapes every decision after it. This lesson teaches you to describe a column of numbers so that the summary matches the data: the right centre, the right spread, the outliers, the shape, and how many values it rests on.

By the end you can

  • Choose between mean and median, and explain how skew pulls them apart
  • Read and compute percentiles (p50, p90, p99), the IQR and the standard deviation in a spreadsheet, Python and SQL
  • Find outliers with IQR fences, and explain why z-scores mislead on skewed data
  • Read a histogram, change its bin width and scale, and spot two groups mixed together
  • Write a one-paragraph summary that always states n

The everyday picture

Ten people sit in a small café. Their average yearly income is about $30,000. Then a famous footballer walks in and orders a coffee. The average income in the room jumps to over $1 million. Nobody in the room got richer. The middle person, the one with five people poorer and five richer, earns about the same as before.

That is the whole lesson in one scene. One summary number (the average) moved because of one unusual value. Another (the middle value) barely moved. A good description says which number you used, shows the footballer instead of hiding him, and says how many people were in the room.

Mean, median and skew

The is the sum divided by the count. Picture each value as a weight on a ruler: the mean is the point where the ruler balances. A weight far out on one side moves the balance point a lot. The is the middle value after sorting. It only cares about order, so a far-out value moves it at most one place.

Here are ten Mangrove app baskets, in dollars: 7, 9, 10, 12, 13, 15, 17, 20, 23 and 58. The $58 order is someone's big monthly shop. The ten add up to $184, so the mean is $18.40. The median sits between the fifth and sixth values, 13 and 15, so it is $14. Seven of the ten baskets are below the mean. Remove the $58 order and the mean drops to $14.00, while the median only moves from $14 to $13.

When most values are small and a few are very large, the data is : it has a long tail to the right. Money data is almost always like this: basket sizes, incomes, order values, time spent on a task. On right-skewed data the mean is above the median, and most values are below the mean. So "the average customer" describes a basket that most customers don't buy.

The same thing happens across all of Mangrove's app orders. On a normal day there are about 60,000. Their mean basket is $18.40 and their median is about $14. About two orders in three are below the mean.

60,000 orders, one day median $14 mean $18.40 p90 $38 a second bump $0 $20 $40 $60 basket size, $5 bins
Each bar is the share of orders in a $5 range. The two tallest bars, $5 to $15, hold about half of all orders. The long right tail pulls the mean ($18.40) well to the right of the median ($14). Nine orders in ten are below $38. The bump around $35 to $40 is explained later in this lesson.

Which one should you report? Ask what the decision needs. If you need a total, such as how much cash riders will collect tomorrow, the mean is right: mean × count = total, and the big orders really do add up. If you need the typical customer, such as what most people put in a basket, the median is right. When in doubt, report both, and treat a big gap between them as a signal about shape.

Quick check

Finance wants to forecast next week's app revenue from 420,000 expected orders. Which basket number should they multiply by?

Percentiles and spread

A answers "how big is the value that X% of orders stay under?" The median is p50. p90 is the value 90% of orders are below, and p99 the value 99% are below. For Mangrove's baskets, p90 is about $38 and p99 about $52. Percentiles describe the tail, which a mean hides.

Percentiles are how service promises work. When 91% of "Now" orders arrive within 30 minutes, that is the same fact as "the 91st percentile of delivery time is 30 minutes". A median delivery time of about 21 minutes says nothing about the 9% who waited longer. That is why people who run a service watch p90 and p99, the slow end, and not only the middle.

How is a percentile computed when it falls between two values? Most tools sort the values and use the position (n − 1) × p, counting from 0, and draw a straight line between the two neighbours. For the ten baskets, p90 sits at position 9 × 0.9 = 8.1, a tenth of the way from $23 to $58: $26.50. Excel's and Google Sheets' PERCENTILE.INC, numpy's np.percentile and pandas' quantile (with their default settings), and Postgres's percentile_cont all give $26.50. Other methods exist. PERCENTILE.EXC uses position (n + 1) × p and gives $54.50 here, and Postgres's percentile_disc returns a real value from the data, $23. With ten values the method changes the answer a lot; with 60,000 it barely matters. Pick one, and use the same one every week.

Small samples also make the extreme percentiles fragile. A p99 from 50 orders is decided by the two largest orders. With 60,000 orders a day, about 600 orders are above p99, so the number is stable. A rough rule: only report p99 when you have at least a few hundred values, and always state n beside it.

Spread is how far values sit from each other. Three measures are common:

  • Range: maximum minus minimum. For the ten baskets, 58 − 7 = $51. It depends only on the two most extreme values, so one odd order decides it.
  • : p75 minus p25, the width of the middle half. For the ten baskets, Q1 = $10.50 and Q3 = $19.25, so the IQR is $8.75. For all 60,000 orders it is about $15 (from about $9.60 to $24.60). The extreme values don't touch it.
  • (SD): take each value's distance from the mean, square it, add them up, divide by n − 1, and take the square root. For the ten baskets it is $14.77.

Squaring gives big distances a big voice. The $58 basket is 39.6 from the mean; squared, that is 1,568 of the total 1,964, about 80% of the sum. Without it the SD of the other nine is $5.27. One order nearly triples the SD. On skewed data, an SD describes the tail more than the typical spread.

Two versions of the SD exist. Dividing by n − 1 gives the sample SD, the right choice when your data is a sample from something bigger (the reason is part of Samples, uncertainty and confidence intervals, later in this course). Dividing by n gives the population SD. Spreadsheets have STDEV.S and STDEV.P. Watch the Python defaults: pandas' .std() divides by n − 1, while numpy's np.std divides by n unless you pass ddof=1. Postgres has stddev_samp and stddev_pop. With thousands of values the two barely differ; with ten values they differ by about 5% ($14.77 against $14.02).

A quick test for skew: compute mean − 2 × SD. For the ten baskets it is 18.40 − 29.55 = −$11.15, and for all app orders about −$6. No basket is negative. When "two SDs below the mean" is impossible, the data is skewed and the rules you may know for bell-shaped data, such as "95% of values within 2 SDs", do not apply.

Quick check

A report says "p90 delivery time: 29 minutes (n = 40)". A colleague recomputes it from the same 40 orders and gets 31 minutes. Neither made a typing error. What is the most likely reason?

Finding outliers: IQR fences and z-scores

An is a value far from the rest. Two methods are common for finding them, and on skewed data one of them fails.

IQR fences, from John Tukey's box plot, set the fences at Q1 − 1.5 × IQR and Q3 + 1.5 × IQR. Anything outside is flagged. For the ten baskets: 10.50 − 13.13 = −$2.63 and 19.25 + 13.13 = $32.38. The $58 order is outside the upper fence and gets flagged. The fences are built from quartiles, so the outlier can't move them. Tukey also used 3 × IQR for values he called "far out".

A is (value − mean) ÷ SD, and a common rule flags |z| > 3. For the $58 order: (58 − 18.40) ÷ 14.77 = 2.68. Not flagged. The outlier inflated both the mean and the SD it is measured against, so it hid itself. This is called . On skewed data the z-rule is also lopsided: the lower fence (mean − 3 SD) is far below zero, so it can only ever flag large values.

Ten baskets IQR fences fence $32.38 flagged z-score rule mean mean + 3 SD = $62.72 missed: z 2.7 $0 $20 $40 $60
Top: the ten baskets. Middle: a box plot. The box runs from Q1 to Q3 with the median inside, the whiskers reach the furthest values inside the fences, and the $58 order is outside the upper fence. Bottom: the $58 order pushed the mean and SD up, so mean + 3 SD lands at $62.72 and the z-rule misses it.

Fences have their own trap at scale. On all 60,000 app orders the upper fence is about $47, and about 2.5% of orders, roughly 1,500 a day, are above it. Nearly all of them are ordinary big scheduled shops. On right-skewed data, run the fences on the logarithm of the values (on a log scale the baskets look roughly symmetric); there they flag almost nothing, which is the truth.

A flag is a question, never a verdict. For each flagged value, find out which kind it is:

  • An error: a test order, a duplicate, a price typed in dollars where the system expects cents. Fix it at the source if you can, remove it if you can't, and write down what you removed and why.
  • Real but rare: a customer buying for a wedding. Keep it. If it distorts a summary, report a median or the result with and without it. Deleting real customers to make a chart prettier is how analyses start to lie.

Quick check

In a sample of 10 values, can any value have a z-score above 3 (using the sample SD)?

Shape: bins, log scales and two groups in one column

A splits the values into equal ranges, called bins, and draws how many fall in each. The bin width changes what you see. Too wide and real features disappear; too narrow and every bar is noise. Always try at least two widths. In most tools you can set the bin width directly (in Python, plt.hist(x, bins=...) takes a number of bins or a list of edges).

With $20 bins the app baskets look like one smooth slope: 69% of orders under $20, 23% from $20 to $40, 8% from $40 to $60. With $5 bins (the first diagram) the bars fall, then rise again around $35 to $40. A dip followed by a second rise is a sign of data: two groups mixed in one column.

Here the two groups are the two kinds of app order. About four orders in five are "Now" orders, 30-minute top-ups: a few items, median about $12, mean about $13.30. One in five is a "Later" order, a scheduled big shop: median about $38, mean about $38.80. Mixed together they give the overall mean of $18.40 (0.8 × 13.30 + 0.2 × 38.80), a number that describes neither group well. Most of the long tail in the first diagram is Later orders.

All orders, $20 bins one smooth slope Now orders, $5 bins median $12 Later orders, $5 bins median $38 $0 $20 $40 $60
Top: wide bins hide the dip between the groups. Middle and bottom: the same orders split by channel, each drawn as a share of its own group. Now orders (4 in 5) and Later orders (1 in 5) are two different shapes with two different typical baskets.

A helps with right-skewed data. On a log axis, $5, $10, $20 and $40 sit at equal distances, because each is double the one before. The long tail gets squeezed and the bulk gets room, so you can see the shape of both. Basket sizes, incomes and response times often look roughly symmetric on a log scale. In a spreadsheet you can add a column with =LN(A2) and chart that; in matplotlib, ax.set_xscale("log") with bins spaced by np.geomspace.

The fix for mixed groups is to split before you summarise. Describe Now and Later orders separately, and only quote an overall number when the decision really is about all orders together. The same goes for any column that mixes stores and the app, weekdays and festival days, or new and returning customers.

Finally, always report n, the number of values a summary rests on. A ranking of 320 stores by average app basket once put a new store at the top with $31. It had 11 orders, two of them big monthly shops. An average of 11 orders and an average of 2,000 orders are different kinds of evidence, and the reader can only tell them apart if you write the n. How much an average from a small n can move is the subject of the next lesson.

Do it

Describe one numeric column of your own data the same way three times: spreadsheet, Python and SQL.

  1. Count first

    Write down n, how many values are missing, and the minimum and maximum. A negative basket or a $9,999 order is found here, before any average.

  2. Compute the summary

    Mean, median, Q1, Q3, p90, p99, SD and the IQR fences. Pick a tab.

    Output
    Baskets in dollars in A2:A60001 (Excel and Google Sheets)
    n          =COUNT(A2:A60001)
    mean       =AVERAGE(A2:A60001)
    median     =MEDIAN(A2:A60001)
    Q1         =QUARTILE.INC(A2:A60001, 1)       (put it in H2)
    Q3         =QUARTILE.INC(A2:A60001, 3)       (put it in H3)
    p90        =PERCENTILE.INC(A2:A60001, 0.9)
    p99        =PERCENTILE.INC(A2:A60001, 0.99)
    SD         =STDEV.S(A2:A60001)
    upper fence  =H3 + 1.5 * (H3 - H2)           (put it in H4)
    flagged      =COUNTIF(A2:A60001, ">" & H4)
  3. Draw it twice

    Make a histogram with two bin widths, and one on a log scale. Look for a long tail, a second bump, and values piled up at a round number or at zero.

    Python
    import matplotlib.pyplot as plt
    
    fig, (left, right) = plt.subplots(1, 2, figsize=(10, 4))
    left.hist(basket, bins=np.arange(0, 105, 5))          # $5 bins from $0 to $100
    right.hist(basket, bins=np.geomspace(1, 200, 40))     # bins evenly spaced on a log axis
    right.set_xscale("log")
    plt.show()
    SQL
    -- $5 bins in SQL: bucket 1 is $0 to $4.99, bucket 21 is $100 and over
    SELECT width_bucket(total_cents, 0, 10000, 20) AS bucket, count(*) AS orders
    FROM "order"
    GROUP BY bucket
    ORDER BY bucket;
  4. Split, check, write

    If the shape has two bumps, find the column that separates them and repeat step 2 per group. Check every flagged value. Then write the summary.

    Markdown
    ## App baskets, Monday 19 October 2026
    - n = 60,000 orders (3 staff test orders removed, listed in the notes)
    - Typical basket: median $14 (Now $12, Later $38). Mean $18.40, pulled up by Later orders.
    - Spread: middle half from $9.60 to $24.60 (IQR $15); 9 in 10 orders under $38.
    - Shape: right-skewed, two groups (Now 80%, Later 20%). Summaries are split by channel.
    - Outliers: almost none once the test orders are removed and the fences run on the log scale.

Bring it to your team

Ask these whenever a single summary number is on a slide.

  • Is that a mean or a median, and how far apart are the two?
  • What is n? How many values did we remove, and why?
  • What happens at the slow or expensive end: what are p90 and p99?
  • Are two groups mixed in this number, such as Now and Later orders, or stores and the app?
  • Have we looked at a histogram, at more than one bin width?

Red flags

  • "The average customer" used for a skewed money column, with no median beside it.
  • A mean ± SD on data that can't be negative, where mean − 2 SD is below zero.
  • Outliers removed with a z-score rule and no list of what was removed.
  • A ranking of stores or riders by average with no n, where the top entries have a handful of values.
  • A percentile quoted with no note of the method, compared with one from another tool.

Practice

Summarise baskets per channel in SQL

The table "order"(id, channel, total_cents) holds 18 app orders. channel is now or later. Return one row per channel with the columns channel, orders (n), mean_cents, median_cents and p90_cents. Use percentile_cont for the median and p90, and round each money value to whole cents with round(x::numeric). Then compare the mean and median of Now orders: what pulled them apart?

SQL exerciseRuns in a real PostgreSQL inside your browser
-- Basket summary per channel ('now' and 'later')
-- The starter gives one average for all orders. Change it so that it:
--   1. returns one row per channel (add channel and GROUP BY channel)
--   2. counts the orders as orders
--   3. adds median_cents and p90_cents:
--      percentile_cont(0.5) WITHIN GROUP (ORDER BY total_cents)
-- Round every money value with round(x::numeric)
SELECT round(avg(total_cents)::numeric) AS mean_cents
FROM "order";
Ctrl + Enter runs
Show a solution
SQL
SELECT channel,
       count(*) AS orders,
       round(avg(total_cents)::numeric) AS mean_cents,
       round((percentile_cont(0.5) WITHIN GROUP (ORDER BY total_cents))::numeric) AS median_cents,
       round((percentile_cont(0.9) WITHIN GROUP (ORDER BY total_cents))::numeric) AS p90_cents
FROM "order"
GROUP BY channel;

Now orders have a mean of $19.95 and a median of $12.35. One $98.50 Now order pulls the mean up by more than $7; without it the other eleven average $12.81. The median doesn't notice it. Later orders are more even: mean $39.93, median $38.50. percentile_cont interpolates like PERCENTILE.INC: Now's p90 sits at position 11 × 0.9 = 9.9, nine tenths of the way from $17.60 to $23.80, which is $23.18.

Pass the exercise to finish this task.

Write a percentile function and IQR fences in JavaScript

Write percentile(values, p) that works like PERCENTILE.INC: sort a copy of the values, find position h = (n − 1) × p, and interpolate between the values at Math.floor(h) and the next one. p is a fraction from 0 to 1. Then write iqrFences(values) that returns { low, high }: Q1 − 1.5 × IQR and Q3 + 1.5 × IQR. The tests use the ten baskets from this lesson.

JavaScript exerciseRuns in your browser with tests
function percentile(values, p) {
  // 1. copy and sort ascending: [...values].sort((a, b) => a - b)
  // 2. h = (n - 1) * p, lo = Math.floor(h)
  // 3. return sorted[lo] + (h - lo) * (sorted[lo + 1] - sorted[lo])
  //    (careful when lo is the last index)
  return values[Math.floor(values.length * p)];
}

function iqrFences(values) {
  // Q1 = percentile(values, 0.25), Q3 = percentile(values, 0.75), IQR = Q3 - Q1
  return { low: 0, high: 0 };
}
Ctrl + Enter runs
Show a solution
JavaScript
function percentile(values, p) {
  const sorted = [...values].sort((a, b) => a - b);  // copy, so the input is unchanged
  const h = (sorted.length - 1) * p;
  const lo = Math.floor(h);
  if (lo + 1 >= sorted.length) return sorted[lo];    // p = 1: the maximum
  return sorted[lo] + (h - lo) * (sorted[lo + 1] - sorted[lo]);
}

function iqrFences(values) {
  const q1 = percentile(values, 0.25);
  const q3 = percentile(values, 0.75);
  const iqr = q3 - q1;
  return { low: q1 - 1.5 * iqr, high: q3 + 1.5 * iqr };
}

Q1 is $10.50, Q3 is $19.25 and the IQR is $8.75, so the fences are −$2.63 and $32.38: the $58 basket is outside. Note the copy: sort changes an array in place, and a summary function should never reorder the caller's data.

Pass the exercise to finish this task.

Check yourself

Rider waiting time at stores has a median of 4 minutes and a mean of 9 minutes. The operations lead wants one number for "how long a typical rider waits". What do you report?

You flag outliers in 50,000 order values with "|z| > 3" and find almost none, though the histogram has a long right tail with some orders 20 times the median. Why?

A histogram of app delivery times, with 10-minute bins, shows one wide hump. With 2-minute bins it shows two peaks, around 22 minutes and around 95 minutes. What should you do next?

Flashcards

Open my review

Key takeaways

  • Choose the centre by the decision: the mean for totals, the median for the typical case. On skewed data they differ, and the gap tells you about shape.
  • Describe spread with percentiles and the IQR; the SD is dominated by the tail on skewed data, and n − 1 versus n matters in your tool's defaults.
  • Flag outliers with IQR fences (on a log scale for money data), never with z-scores alone, and check each flag before removing anything.
  • Look at histograms at two bin widths and on a log scale; two peaks mean two groups to split before summarising.
  • Always write n, and what you removed. The $18.40 "average basket" is honest only beside its $14 median, its two channels and its 60,000 orders.

Sources and further reading

Episode transcriptThe basket nobody actually buys · about 10 minutes · tap any line to play from there
  1. NadiaImran, quick question. What does a typical Mangrove app customer spend on one order?
  2. ImranEighteen dollars forty. It's on every slide. The average basket.
  3. NadiaThat's the average. But about two orders in three are below it. So is it typical?
  4. ImranTwo in three below the average? That sounds wrong. Shouldn't it be half and half?
  5. NadiaOnly when the data is symmetric. Basket sizes aren't. That's what today is about: how to describe a column of numbers so the summary matches the data.
  6. NadiaPicture ten people in a small café. Their average yearly income is about thirty thousand dollars. Then a famous footballer walks in and orders a coffee.
  7. ImranAnd the average income in the room goes through the roof.
  8. NadiaOver a million dollars. Nobody got richer. But the middle person, with five people poorer and five richer, earns about the same as before.
  9. ImranSo the average moved because of one person, and the middle value barely noticed.
  10. NadiaExactly. The average is the mean. The middle value is the median. Let's do it with real baskets. Ten app orders, in dollars: seven, nine, ten, twelve, thirteen, fifteen, seventeen, twenty, twenty-three, and fifty-eight.
  11. ImranThe fifty-eight is somebody's big monthly shop.
  12. NadiaRight. They add up to a hundred and eighty-four, so the mean is eighteen forty. The median is halfway between thirteen and fifteen, so fourteen. And seven of the ten are below the mean.
  13. ImranAnd if I take out the fifty-eight?
  14. NadiaThe mean drops to fourteen. The median only moves from fourteen to thirteen. That's skew. A long tail of big values pulls the mean up, and most values end up below it.
  15. ImranAnd the first diagram shows the whole day, I think. Sixty thousand orders.
  16. NadiaYes. If you can see it, it's a histogram, bars for each five-dollar range. If not, picture tall bars between five and fifteen dollars, about half of all orders, and then a long tail stretching to the right. The median is at fourteen, the mean at eighteen forty, and nine orders in ten are below about thirty-eight.
  17. ImranSo should I stop using the mean?
  18. NadiaNo. Ask what the decision needs. If finance forecasts revenue, they need the mean, because mean times count gives the total. Using the median there would undercount by about four dollars an order.
  19. ImranAnd for the typical customer, the median.
  20. NadiaYes. And when in doubt, report both. A big gap between them is a clue about the shape.
  21. ImranWhere do percentiles come in? People keep saying p ninety at me.
  22. NadiaA percentile is the value a given share of orders stay under. The median is p fifty. p ninety is the value ninety percent are below. For our baskets, p ninety is about thirty-eight dollars and p ninety-nine about fifty-two.
  23. ImranAnd our delivery promise is a percentile too, now that I think of it. Ninety-one percent of Now orders arrive within thirty minutes.
  24. NadiaSame fact. The ninety-first percentile of delivery time is thirty minutes. A median of about twenty-one minutes says nothing about the nine percent who waited longer.
  25. ImranHere's a trap I've seen. Two people compute p ninety from the same data and get different answers.
  26. NadiaTools use different methods. With our ten baskets, the spreadsheet function PERCENTILE dot INC gives twenty-six fifty. PERCENTILE dot EXC gives fifty-four fifty. Postgres has a version that returns a real value from the data, twenty-three.
  27. ImranThat's a huge difference.
  28. NadiaWith ten values, yes. With sixty thousand, it barely matters. Pick one method and keep it. And only report p ninety-nine when you have a few hundred values at least.
  29. ImranWhat about spread? I know the standard deviation.
  30. NadiaFor the ten baskets it's about fourteen seventy-seven. Now watch. Without the fifty-eight, it's five twenty-seven.
  31. ImranOne order nearly triples it?
  32. NadiaBecause the standard deviation squares distances. That one order is about eighty percent of the squared total. On skewed data the standard deviation mostly describes the tail. The IQR, the width of the middle half, doesn't care about the extremes. For all our orders it's about fifteen dollars.
  33. ImranAnd there's a sample and a population version of the standard deviation, right?
  34. NadiaYes, and the Python defaults differ. pandas divides by n minus one, like STDEV dot S. numpy divides by n unless you tell it otherwise. With thousands of values it hardly matters. With ten, it's about five percent.
  35. ImranNow outliers. My instinct is z-scores. Anything more than three standard deviations from the mean is an outlier.
  36. NadiaThat's the common instinct, and on skewed data it fails. The second diagram shows why. The fifty-eight dollar order has a z-score of about two point seven. Not flagged.
  37. ImranBut it's obviously the odd one out.
  38. NadiaIt pushed up the mean and the standard deviation it's measured against, so it hid itself. That's called masking. And with only ten values, no value can ever reach three. The ceiling is about two point eight five.
  39. ImranSo what works?
  40. NadiaTukey's fences. Take the first and third quartiles, ten fifty and nineteen twenty-five. The IQR is eight seventy-five. Go one and a half IQRs beyond each quartile. The upper fence lands at about thirty-two forty, and the fifty-eight is outside it.
  41. ImranBecause quartiles don't move when the outlier does.
  42. NadiaRight. But at scale, fences have a trap too. On all sixty thousand orders the upper fence is about forty-seven dollars, and about fifteen hundred orders a day are above it. Almost all of them are ordinary big scheduled shops.
  43. ImranSo the fence flags real customers.
  44. NadiaOn money data, run the fences on a log scale and they flag almost nothing, which is the truth. And a flag is a question, never a verdict. A test order or a price typed in the wrong unit, you fix or remove, and write down. A customer buying for a wedding, you keep.
  45. ImranEarlier you said the first chart had a second bump around thirty-five to forty dollars.
  46. NadiaGood catch. With twenty-dollar bins you'd never see it. The chart looks like one smooth slope. With five-dollar bins, the bars fall, dip, and rise again. That dip usually means two groups mixed in one column.
  47. ImranNow and Later orders.
  48. NadiaYes. The third diagram splits them. About four orders in five are Now orders, quick top-ups, median about twelve dollars. One in five is a Later order, a scheduled big shop, median about thirty-eight. The overall mean of eighteen forty describes neither group well.
  49. ImranWhich is exactly what happened with my growth team's free delivery idea.
  50. NadiaTell it.
  51. ImranThey proposed free delivery on baskets of twenty dollars or more. The slide said the average basket is eighteen forty, so a typical customer only needs to add a little.
  52. NadiaAnd Tomás described the column first.
  53. ImranHe did. First he found three staff test orders of about two and a half thousand dollars each and removed them, with a note. Then the real picture. About seven orders in ten are under twenty dollars. The median Now customer would need to add about eight dollars, two-thirds more.
  54. NadiaAnd the Later orders?
  55. ImranAlmost all already above twenty. So we'd give free delivery to about twelve thousand orders a day without changing a single basket. We changed the proposal to a threshold for Now orders only, tested as an experiment.
  56. NadiaOne last habit. Always report n, how many values a summary rests on. A store ranking once put a new store at the top for average basket. It had eleven orders, two of them big monthly shops.
  57. ImranSo what does the Do it section have me do?
  58. NadiaPick one numeric column from your own data. Count first: n, missing values, minimum and maximum. Then compute the mean, median, quartiles, p ninety, p ninety-nine, standard deviation and the fences, in a spreadsheet, in pandas, or in SQL with percentile cont.
  59. ImranThen draw it.
  60. NadiaTwice, at two bin widths, and once on a log scale. If there are two bumps, find the column that separates them and summarise each group. Then write a short summary that states n and what you removed.
  61. ImranAnd in the practice, I write that per-channel summary in SQL, and a percentile function in JavaScript.
  62. NadiaYes. Here's one to think about. A report says the median rider wait at stores is four minutes and the mean is nine. What does that gap tell you? Take a second.
  63. ImranThe mean is more than double the median, so there's a long tail of long waits. Most riders wait less than nine minutes.
  64. NadiaRight. So report the median for the typical wait, and p ninety beside it for the long waits.
  65. ImranLet me sum up. One, pick the mean for totals and the median for the typical case. Two, flag outliers with fences, not z-scores. Three, look at the histogram, and if it has two humps, split before you summarise.
  66. NadiaGood. I'd add: write n beside every number, and list what you removed. Eighteen forty is honest only next to its fourteen dollar median and its sixty thousand orders.
  67. ImranNext time?
  68. NadiaNext time, we only have a sample of forty stores out of three hundred and twenty. How sure can we be about all of them?
Finished reading?Mark it complete to fill in its stop on your course line.

Use it at work

KPI dashboard notebook

Weekly revenue, orders, average basket and active customers, with a chart per KPI.

Open in the Data Lab
Next stopSamples, uncertainty and confidence intervals
Was this lesson helpful?
Questions and discussion

Loading the discussion…