Forecasting
Parcel Volume Forecasting
- Company
UPS- Job positions
- Data ScientistData AnalystBusiness Analyst
- Topics
- Time seriesDemand forecastingSeasonalityHoliday effectspandas
The scenario
UPS: Forecast daily parcel volume for each sort hub through December, and turn the forecast into a staffing plan.
UPS sorts parcels at eight hubs, and December brings far more of them than any other month. Each hub books seasonal crews weeks ahead, so it needs a daily forecast rather than a monthly total, and running short is worse than running over because parcels then miss their delivery date. You're an analyst on the industrial engineering team, and the crew bookings have to go in before peak starts.
Your task
Forecast daily outbound parcels per hub for December 1 to December 28, 2025, beat a naive forecast on a held-out window, and turn the result into planned crew hours.
Instructions
- 1Load and clean the three years of history. Check for repeated rows and missing days, and explain how you handled each.
- 2Plot each hub's daily volume. Describe the weekly pattern, the yearly growth, the days the building effectively closes, and the shape December takes.
- 3Look for days whose volume does not fit the pattern, decide whether each is real demand or a problem in the building, and say how you treated it.
- 4Check whether every hub has grown the same way, and build your forecast on the level each one runs at now.
- 5Work out when a sale actually moves parcels, using the days around Black Friday and Cyber Monday.
- 6Hold out the last few weeks and forecast them, against a naive forecast of the same date a year earlier. Score both with weighted absolute percentage error, or WAPE, which is total absolute error divided by total actual volume, so the near-empty holidays do not dominate.
- 7Forecast December 1 to December 28 for all eight hubs and turn each day into planned crew hours, given that a missed parcel costs $2.80 and an idle crew hour costs $38. Save forecast.csv with the columns hub_id, date, parcels_outbound_forecast and crew_hours_planned.
Datasets
All files come in one download.
daily_volume.csv
Daily sort volume for eight hubs from January 1, 2023 to November 30, 2025.
8,524 rows · 7 columns · 349 KB
| Column | Type | Description |
|---|---|---|
| hub_id | text | The sort hub. |
| date | date | The sort day. |
| parcels_inbound | integer | Parcels delivered into the building that day. |
| parcels_outbound | integer | Parcels sorted and sent on that day. This is what you forecast. |
| trailers_unloaded | integer | Trailers unloaded at the inbound dock. |
| sort_hours_staffed | integer | Crew hours the hub actually staffed that day. |
| parcels_missorted | integer | Parcels sent to the wrong destination and handled again. |
Preview the first 5 rowsHide preview
| hub_id | date | parcels_inbound | parcels_outbound | trailers_unloaded | sort_hours_staffed | parcels_missorted |
|---|---|---|---|---|---|---|
| LOU | 2023-01-01 | 10133 | 9790 | 9 | 422 | 18 |
| LOU | 2023-01-02 | 511590 | 511361 | 483 | 21104 | 9631 |
| LOU | 2023-01-03 | 439720 | 425289 | 421 | 17348 | 5793 |
| LOU | 2023-01-04 | 420356 | 401037 | 377 | 16005 | 4573 |
| LOU | 2023-01-05 | 414748 | 416808 | 372 | 19311 | 4489 |
hubs.csv
The eight sort hubs and what each one can handle.
8 rows · 7 columns · 1 KB
| Column | Type | Description |
|---|---|---|
| hub_id | text | Unique ID of the hub. |
| hub_name | text | Name of the building. |
| city | text | City the hub is in. |
| state | text | US state the hub is in. |
| region | text | Operating region the hub reports to. |
| sort_capacity_per_hour | integer | Parcels the hub can sort in an hour at full crew. |
| crew_size | integer | People on a full sort crew. |
Preview the first 5 rowsHide preview
| hub_id | hub_name | city | state | region | sort_capacity_per_hour | crew_size |
|---|---|---|---|---|---|---|
| LOU | Louisville Air Hub | Louisville | KY | Central | 46000 | 1750 |
| DFW | Dallas Regional Sort | Dallas | TX | South | 21000 | 860 |
| ONT | Ontario West Sort | Ontario | CA | West | 23500 | 940 |
| PHL | Philadelphia Metro Sort | Philadelphia | PA | Northeast | 18000 | 720 |
| CHI | Hodgkins Area Hub | Hodgkins | IL | Central | 20500 | 810 |
calendar_days.csv
Every date from January 1, 2023 to December 28, 2025, including the dates you forecast.
1,093 rows · 6 columns · 34 KB
| Column | Type | Description |
|---|---|---|
| date | date | The calendar date. |
| day_of_week | text | Day name, from Sunday to Saturday. |
| is_holiday | text | Whether the day is a holiday the network observes: yes or no. |
| holiday_name | text | Name of the holiday. Empty on days that are not holidays. |
| is_peak_season | text | Whether the day falls in peak season: yes or no. |
| retail_promo_event | text | black_friday, cyber_monday, prime_day or none. |
Preview the first 5 rowsHide preview
| date | day_of_week | is_holiday | holiday_name | is_peak_season | retail_promo_event |
|---|---|---|---|---|---|
| 2023-01-01 | Sunday | yes | New Year's Day | no | none |
| 2023-01-02 | Monday | no | empty | no | none |
| 2023-01-03 | Tuesday | no | empty | no | none |
| 2023-01-04 | Wednesday | no | empty | no | none |
| 2023-01-05 | Thursday | no | empty | no | none |
Hints
A forecast of the same date a year ago lands on a different day of the week, which is most of why it does badly. Handling the day of the week and the shape of December separately avoids that.
volume["weekday"] = pd.to_datetime(volume["date"]).dt.day_name()
volume.groupby("weekday")["parcels_outbound"].mean()A day with normal volume arriving into the building and nothing leaving it is not a quiet day. Comparing inbound against outbound separates the two.
Deliverable
A public GitHub repo with your analysis (a notebook or scripts), forecast.csv covering every hub and date in December, and a README with the patterns you found, your held-out error and the reasoning behind the staffing plan.
When you're done, post your repo in the Solutions tab to share it with other learners.
What grading checks
Use this checklist to review your own work before you post and share it.
- Submitted GitHub repo is public and reachable.
- Repo contains at least one notebook or script file.
- forecast.csv has a forecast and planned crew hours for all eight hubs on every date from December 1 to December 28.
- WAPE is 18 percent or better on December, against 30 percent for the naive forecast.
- Under the cost assumptions in the brief, the staffing plan costs less than a flat crew level every day.
- The days that do not fit the pattern are identified and kept out of the trained pattern, with the reasoning given.
- Growth is checked per hub so the forecast follows the level each runs at now, and accuracy is reported on a held-out window rather than fitted history.