The question
Help the café team compare demand for each drink after normalising inconsistent labels.
df Demand comparisonYour inputs
df
One row is one café order. Spaces and letter case in drink labels are inconsistent; every order belongs in this comparison.
Field meanings and units
order_id- Order or order-line identifier, as defined by this brief.
drink- Recorded drink label.
size- Recorded serving size.
price- Price in dollars; unparseable text needs the stated policy.
tip- Tip in dollars.
shift- AM or PM service period.
date- Calendar date supplied as YYYY-MM-DD text unless the task states it is invalid.
order_id | drink | size | price | tip | shift | date |
|---|---|---|---|---|---|---|
| C001 | " Latte " | Small | 4.5 | 0 | AM | 2026-04-01 |
| C002 | tea | Large | 2.8 | 1 | PM | 2026-04-01 |
| C003 | LATTE | Small | 4.5 | 0.5 | AM | 2026-04-02 |
| C004 | " Mocha" | Large | 5.2 | None | AM | 2026-04-02 |
| C005 | " Latte " | Small | 4.5 | 0 | PM | 2026-04-03 |
View all 20 rows
order_id | drink | size | price | tip | shift | date |
|---|---|---|---|---|---|---|
| C001 | " Latte " | Small | 4.5 | 0 | AM | 2026-04-01 |
| C002 | tea | Large | 2.8 | 1 | PM | 2026-04-01 |
| C003 | LATTE | Small | 4.5 | 0.5 | AM | 2026-04-02 |
| C004 | " Mocha" | Large | 5.2 | None | AM | 2026-04-02 |
| C005 | " Latte " | Small | 4.5 | 0 | PM | 2026-04-03 |
| C006 | tea | Large | 2.8 | 1 | AM | 2026-04-03 |
| C007 | LATTE | Small | 4.5 | 0.5 | AM | 2026-04-04 |
| C008 | " Mocha" | Large | 5.2 | None | PM | 2026-04-04 |
| C009 | " Latte " | Small | 4.5 | 0 | AM | 2026-04-05 |
| C010 | tea | Large | 2.8 | 1 | AM | 2026-04-05 |
| C011 | LATTE | Small | 4.5 | 0.5 | PM | 2026-04-06 |
| C012 | " Mocha" | Large | 5.2 | None | AM | 2026-04-06 |
| C013 | " Latte " | Small | 4.5 | 0 | AM | 2026-04-07 |
| C014 | tea | Large | 2.8 | 1 | PM | 2026-04-07 |
| C015 | LATTE | Small | 4.5 | 0.5 | AM | 2026-04-08 |
| C016 | " Mocha" | Large | 5.2 | None | AM | 2026-04-08 |
| C017 | " Latte " | Small | 4.5 | 0 | PM | 2026-04-09 |
| C018 | tea | Large | 2.8 | 1 | AM | 2026-04-09 |
| C019 | LATTE | Small | 4.5 | 0.5 | AM | 2026-04-10 |
| C020 | " Mocha" | Large | 5.2 | None | PM | 2026-04-10 |
The editable setup in Your Python creates these inputs when you run it.
Help the café team compare demand for each drink after normalising inconsistent labels.
countsSeriesfigFigureDeliverables
Make the outputs listed below. Use each name exactly as shown. Then choose Check answer.
Python name key
Teal outlines name table columns. Violet left rules name Python objects. Dotted rules mark syntax, functions and parameters. Use each name exactly as shown.
- Drink countsOutput
countsSeries- Store the number of orders for each
drinkafter trimming and lowercasing its label incounts. - Keep
df.
- Store the number of orders for each
- FigureOutput
figFigure- Create
figcomparing every category count. - Choose labelled bars or individual points; either orientation is valid.
- Bars must start at zero.
- Add a meaningful title and measure labels
- Display the figure.
Identify Drink and Orders on the appropriate axes; extra wording is welcome.
- Create
Data policy Keep all supplied source tables unchanged. Work on separate outputs.
Help Hints & explained solution
Choose the amount of help you need. Opening one hint does not reveal the others.
Hint 1 — Think
Does each spelling represent a different drink or just different formatting?
Hint 2 — Tools
String accessors, value_counts(), Axes.bar() or Axes.barh(), or Axes.scatter() for a labelled point comparison
Revisit: Clean text · Count categories · Count categories · Finish a chart properly · Scatter plot
Hint 3 — Approach
Standardise labels, count each drink and show all category counts on a zero-based quantitative axis.
Explained solution
Add these lines below # Your work in the editor. The supplied input setup is already there.
work = df.copy()
work['drink'] = work.drink.str.strip().str.lower()
counts = work.drink.value_counts()
fig, ax = plt.subplots()
ax.bar(counts.index, counts.values)
ax.set(title='Café drink demand', xlabel='Drink', ylabel='Orders')
fig.tight_layout()
plt.show()View supplied setup
This code is already at the top of the editor.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# Supplied input: df (20 rows)
df = pd.DataFrame(
[
('C001', ' Latte ', 'Small', 4.5, 0, 'AM', '2026-04-01'),
('C002', 'tea', 'Large', 2.8, 1, 'PM', '2026-04-01'),
('C003', 'LATTE', 'Small', 4.5, 0.5, 'AM', '2026-04-02'),
('C004', ' Mocha', 'Large', 5.2, None, 'AM', '2026-04-02'),
('C005', ' Latte ', 'Small', 4.5, 0, 'PM', '2026-04-03'),
('C006', 'tea', 'Large', 2.8, 1, 'AM', '2026-04-03'),
('C007', 'LATTE', 'Small', 4.5, 0.5, 'AM', '2026-04-04'),
('C008', ' Mocha', 'Large', 5.2, None, 'PM', '2026-04-04'),
('C009', ' Latte ', 'Small', 4.5, 0, 'AM', '2026-04-05'),
('C010', 'tea', 'Large', 2.8, 1, 'AM', '2026-04-05'),
('C011', 'LATTE', 'Small', 4.5, 0.5, 'PM', '2026-04-06'),
('C012', ' Mocha', 'Large', 5.2, None, 'AM', '2026-04-06'),
('C013', ' Latte ', 'Small', 4.5, 0, 'AM', '2026-04-07'),
('C014', 'tea', 'Large', 2.8, 1, 'PM', '2026-04-07'),
('C015', 'LATTE', 'Small', 4.5, 0.5, 'AM', '2026-04-08'),
('C016', ' Mocha', 'Large', 5.2, None, 'AM', '2026-04-08'),
('C017', ' Latte ', 'Small', 4.5, 0, 'PM', '2026-04-09'),
('C018', 'tea', 'Large', 2.8, 1, 'AM', '2026-04-09'),
('C019', 'LATTE', 'Small', 4.5, 0.5, 'AM', '2026-04-10'),
('C020', ' Mocha', 'Large', 5.2, None, 'PM', '2026-04-10'),
],
columns=['order_id', 'drink', 'size', 'price', 'tip', 'shift', 'date'],
)Why these steps exist
- Normalising labels prevents one drink from being split into several categories.
- Category counts are lengths on a common zero-based scale; orientation does not change the evidence.
Another valid approach
Labelled individual points are also valid for comparing these summaries. Vertical and horizontal orientations are accepted; bars must use a zero baseline.