← Back to portfolio
Case Study · Operations Analytics

Turning a week of scattered data requests into a repeatable event-readiness playbook

How iterative, natural-language querying against live fleet, ride, and workforce data — corrected in real time — became the operational plan for a major public event weekend.

ContextMid-size US city · shared micromobility
Data sourcesFleet telemetry · ride logs · timesheets · action logs
Timeframe~10 days, two consecutive event weekends
Systems & Tools / Data & Analytics Pipeline
01 — Context

Two festivals, same city block, one week apart

A mid-size US city hosts back-to-back public festivals in the same downtown park corridor — one over a weekend, the next running one day longer. The operator managing part of the shared micromobility fleet needed to know: what actually happened last weekend, and what has to change before the next one.

Fleet
A mixed fleet of e-scooters and two e-bike models, positioned across zones with very different demand patterns — a nightlife corridor, a downtown waterfront, and a university district.
Workforce
A blended crew of contracted operators and in-house staff, plus a specialized rebalance-only role. Some logged activity looked like field work but was actually warehouse battery diagnostics.
Competitive landscape
A second operator running a comparable fleet in the same city, tracked via public availability feeds — used as a benchmark for uptime and zone density, not named directly.
The ask
Not a single report — a running, corrected analysis across a week of new data drops: fleet snapshots, ride exports, action logs, and payroll data, each refining the picture.
02 — The Query Log

What was actually asked, in order

The real value wasn't any single chart — it was the sequence. Each question either built on the last, corrected a wrong assumption, or surfaced an insight that changed the plan. A condensed, anonymized version of that sequence:

query_history.log
01
Summarize the past week day-by-day, and flag where the plan fell short for the next event build
Produced a daily narrative from inference — reasonable, but not grounded in the actual operator action logs yet.
02
Here are the actual logged actions for that week — redo it fix
Replaced inference with ground truth. Surfaced the real top performers, the real overnight coverage gap, and one operator whose swaps were making the fleet worse, not better.
03
What about the bike fleet specifically — highest revenue trips and where they start? insight
Two bike models split cleanly by zone: one dominated the nightlife/park corridor, the other dominated the downtown/waterfront corridor. Neither model won everywhere.
04
Calculate rides inside this exact event polygon, for this exact time window build
Point-in-polygon filtering against a real festival-boundary shape file, not an approximate radius. Precision mattered — the first polygon supplied was actually 2km from the venue in question.
05
Wait — that day wasn't the event I thought it was fix
A full recalibration. What had been treated as "no event, regular weekend" baseline data was actually the first festival's real performance — meaning it was a benchmark to beat, not a floor to compare against.
06
Apply a historical attendance multiplier to project the next event's demand build
Turned one event's actuals into a forward-looking demand target for the next one — a simple multiplication that changed every staffing and battery-swap number downstream.
07
How many battery swaps were actually needed to hit that target? insight
Converted "the fleet felt low on battery" into an exact number: swaps completed vs. swaps required to hold average charge above a healthy threshold across the event window. The gap was the whole story.
08
One of these workers is a mechanic, not a field operator fix
A single correction that fixed every downstream grading table. Warehouse battery-diagnostic activity looks identical to bad field work in raw exports — same negative deltas — until you separate the role.
09
Break every operator's swaps down by vehicle model build
A worker × model cross-tab exposed who specialized in which vehicle type, and confirmed the model with the worst uptime was also getting the least consistent field attention.
10
Summarize everything as a portfolio case study, anonymized insight
This page.
03 — Lessons Learned

What ten days of iterative querying actually taught

LESSON 01

Get the baseline right before you benchmark anything

The single biggest correction in this whole process was realizing that a data window I'd assumed was a "normal, no-event weekend" was in fact the first festival's actual performance. Every downstream target had been calibrated against the wrong floor.

In practice

Before setting any target number, explicitly confirm what conditions produced the comparison data — don't infer it from the calendar.

LESSON 02

Raw activity logs conflate roles until you separate them

A worker doing warehouse battery-pack diagnostics produces the exact same signature in the data — high starting charge, no completion reading, negative delta — as a field worker doing genuinely bad swaps. Grading them the same way punishes good workers and hides real problems.

In practice

Classify by behavioral pattern (location, start/end values, shift timing) before calculating any performance average across a team.

LESSON 03

Fleet-wide averages hide zone-specific truths

Neither vehicle model was "better" in the abstract. One consistently earned more per trip in the park/nightlife corridor; the other won decisively downtown. A single fleet-wide revenue-per-ride number would have masked both facts and led to the wrong deployment call.

In practice

Always cut performance metrics by the geography or context they occurred in before averaging them into one number.

LESSON 04

Translate a felt problem into an exact number

"The fleet felt low on charge all weekend" isn't actionable. Calculating exact swaps-completed vs. swaps-required against a target average charge turned a vague impression into a specific, schedulable gap — and pointed at exactly which overnight shift needed to change.

In practice

Whenever a problem is described qualitatively, look for the underlying quantity that would make the gap unambiguous.

LESSON 05

Precision on scope changes the answer, not just the decimal places

Filtering "rides in the general area" versus rides inside the exact festival boundary polygon, in the exact permitted time window, produced meaningfully different numbers — and the first boundary shape supplied was, on inspection, over a mile from the actual venue.

In practice

Verify the geographic or temporal scope of an analysis against ground truth before trusting the output, especially when the source data was hand-entered.

LESSON 06

The same operational gap will repeat unless the schedule structurally changes it

An uncovered overnight window showed up as the same battery-health failure point across multiple event nights in the data. Naming it once wasn't enough — the fix had to be a specific shift reassignment, not a general reminder to "cover nights better."

In practice

When a pattern recurs across multiple independent data pulls, treat it as a structural scheduling problem, not a one-off execution miss.

04 — Outcome

What changed operationally

By the time the second festival opened, the plan had shifted from a general "run it like last time" approach to a specific, numbered playbook:

05 — Method

How the analysis actually worked

This wasn't a single big report. It was iterative, conversational, and corrected in real time as new data arrived:

Natural-language querying Multi-source data fusion Point-in-polygon geospatial filtering Behavioral pattern classification Time-series demand forecasting Role-based activity segmentation Zone-level performance stratification Shift-window analysis