AI Hints
Home›Data Science Tutorial›Case Study: Staffing
Data Science · Lesson 84 of 101

Case Study: Staffing the Cafes

Where are we over and under?.

⏱ 2 min read▶ Video at 2:22:47🎓 Free
Watch this lesson in the Data Science courseWatch on YouTube ↗Full Data Science course

Staff are the biggest cost in any cafe. Too few, and the queues drive customers away. Too many, and the profit vanishes. Each manager rosters by instinct. The operations director asks whether data can do better. And it's your job to find out.

Case Study: Staffing the Cafes
From the video: Case Study: Staffing the Cafes
  • Staff are the biggest cost
  • Too few or too many
  • Managers use instinct

Step one: how hard is each cafe working?

We need a fair measure of how busy each cafe is. Total sales would just favour big cafes. So we divide daily units by floor space. Run it. Giza and Milan are at the bottom, at about one unit per square metre. Cairo and Oslo are at the top, with nearly twice that. Those small cafes are working hard, and the large ones have a lot of empty space. Remember Giza and Milan. You'll meet them again in the capstone, when we look at rent.

case2_step1.pypython
import pandas as pd

s = pd.read_csv("sales.csv", parse_dates=["date"])
stores = pd.read_csv("stores.csv")
u = s.groupby("store_id")["units"].sum() / s["date"].nunique()
t = stores.set_index("store_id").assign(daily_units=u)
t["per_m2"] = (t["daily_units"] / t["size_m2"]).round(2)
print(t[["city", "size_m2", "daily_units", "per_m2"]].sort_values("per_m2").round(1).iloc[[0, 1, -2, -1]].to_string())
Output
           city  size_m2  daily_units  per_m2
store_id
8          Giza      171        174.0     1.0
6         Milan      197        222.4     1.1
7         Cairo       73        116.7     1.6
1          Oslo       74        137.2     1.8

Step two: weekends and peaks

Staffing isn't about the average. It's about busy times. We compare weekdays and weekends, then find a busy day, using the ninety fifth percentile. Run it. The average weekday has a hundred and sixty five units. Weekends average two hundred and seven. That's twenty five percent more. And a busy day reaches about two hundred and seventy eight. If you staff for the average, then you'll have queues on your busiest days, and that's when you make the most money. So rosters should follow the rhythm of the week, rather than being the same every day.

case2_step2.pypython
import pandas as pd

s = pd.read_csv("sales.csv", parse_dates=["date"])
s["weekend"] = s["date"].dt.dayofweek >= 5
t = s.groupby(["store_id", "date", "weekend"])["units"].sum().reset_index()
print(t.groupby("weekend")["units"].describe()[["mean", "50%", "max"]].round(0).to_string())
peak = t["units"].quantile(.95)
print("Busy day (95th percentile):", round(peak))
Output
          mean    50%    max
weekend
False    165.0  162.0  351.0
True     207.0  203.0  426.0
Busy day (95th percentile): 278

Step three: turning units into people

Now we need a rule that a manager can use. Let's say that one person can handle twenty two units an hour, across a twelve hour day. Run it. Three hundred and forty units needs about one and a half people on shift at once. Six hundred and twenty needs more than two. These are averages. Remember our queue lesson though. If you run people at full capacity, then queues explode. So you'd round up, and add some slack at peak times. And it's a simple table that any manager can use tomorrow morning.

case2_step3.pypython
units_per_hour = 22
open_hours = 12
for units in [340, 450, 620]:
    staff = units / (units_per_hour * open_hours)
    print(f"{units} units a day: {staff:.1f} people on shift at once")
Output
340 units a day: 1.3 people on shift at once
450 units a day: 1.7 people on shift at once
620 units a day: 2.3 people on shift at once

What you recommend

Here's the page. Recommendation, roster by demand, with twenty five percent more cover at weekends. Pilot this in Oslo and Cairo, the busiest for their size. In Giza and Milan, check whether morning cover can be reduced. Why? Weekends are a quarter busier, and busy cafes risk queues. Risks, the staffing figure of twenty two units an hour is an estimate, so measure it in the pilot. Measure waiting time, sales, and staff satisfaction.

Recommendroster by demand
PilotOslo and Cairo
CheckGiza and Milan cover
Measurewaits, sales, morale

Summary

Normalise fairly, plan for peaks, and give managers a simple rule. Next, a tricky product decision, where the numbers disagree.

Key takeaways
  • Compare per square metre
  • Staff for peaks, not averages
  • Turn analysis into a simple rule
Next up: Case Study: Ship the Redesign? — when metrics disagree