How I (try) to optimize my commute

The Problem

When I took my latest and greatest job, I was struck with the same problem every working stiff has: how do I get to work? In much of the country, I suppose that’s a question more about driving routes, and for our New York brethren it’s really just “what train shows up first?”

But San Francisco is an oddball. It’s dense like New York, so I sold my car and don’t drive anywhere. But unlike New York, our mass transit is widely lauded as missing its potential. Luckily, our combination of density, dysfunction, and eager early-adopter residents means we have a host of alternatives. Uber was born here, tech companies invest in private shuttles, little electrical scooters from Scoot zip across hills, etc.

So what should I do? Admitting ignorance means I had to come up with a way to test the plethora!

I live here, in a neighborhood called Pacific Heights, along an amazing park. And I work there, in the neighborhood called the Mission.

As google maps shows you, it’s a mere 2.5 miles, and fairly straight shot. And as it also shows you, traffic sucks, you can expect to average 7–8 mph in this stretch.

So I took to measuring the various means of transit at my disposal. And after a year-plus of data collection, here’re my best and worst!

The fastest: a tie between Flywheel and UberX. Both average 18 minutes, but I’ve taken Flywheel twice and UberX 28 times.

The slowest: Walking. 48 minutes.

The cheapest (true cost): Walking. $0.

The priciest: Curb. $33.33. But I just did that once, the experience was super negative.

The cheapest (time+cost): Uber Pool. $9.78

The priciest (time + cost): Curb. $35.43

The cushiest: Flywheel. Perfect 5 on comfort (again, just two rides)

The roughest: Curb. Perfectly terrible at 1.

The Approach

To grade the various modes, I decided I would only care about three things:

  • Speed
  • Cost
  • Comfort (1–5 scale)
  • Empty city buses = quiet reading time!
  • UberPools with crammed co-riders that hadn’t showered in days = eye-watering misery

Each morning I got a new row in an excel spreadsheet where I’d log those three bits (now a CSV I update in python). To get to apples-to-apples, I’d convert my commute duration to a dollar amount (hey, time = money!). My per-minute value would be set just by taking total actual dollars spent / total time spent (literally, my time = my money).

  • eg a $2.25 bus ride that took 40 minutes valued my time at 5.6cents per minute.
  • A $32 “prime time” Lyft ride that got me to work in 20 minutes valued my time at $1.60 per minute!

Blending cumulative time and dollars ended up getting an overall value of $0.31 per minute. Thus every commute had two costs: real and time, essentially a 2-D point. Total Cost was then just a calculation of the distance to that point from (0,0).

For comfort it’s a lot easier. I just rate each ride on a 1 to 5 scale. Totally subjective and arbitrary. The worst kind of data.

For both time-cost and comfort, I compare the commute method’s average performance relative to the best average.

  • eg Walking is slowest on average (48 minutes) and UberX fastest (18 minutes), so at best I can shave 30 minutes off my commute. Yellow Cab takes 32 minutes, which means I save 16 minutes from Walking, so it’s Time score would be 16/30 = 0.53

Finally, I weight time-cost as 80% of total score, and comfort as 20%.

By comparing these total costs and comfort scores to the average, I could generate a score for each method I could collect data on.

Time_Cost[‘Bus’] = sqrt(Real_Cost[‘Bus’].average^2
+ (Time[‘Bus’].average * time_value)^2)
Time_Cost_Score[‘Bus’] = (Time_Cost.max — Time_Cost[‘Bus’]) / (Time_Cost.max — Time_Cost.min)
#relative to the best Time_Cost savings, how does this mode compare?
Comfort_Score[‘Bus’] = 1 — (Comfort.max — Comfort[‘Bus’]) / (Comfort.max — Comfort.min)
#relative to the most comfortable, how does this mode compare?
Score[‘Bus’] = 0.8 * Time_Cost_Score[‘Bus’] + 0.2 * Comfort_Score[‘Bus’]

Because I am trying to optimize my commute and not run a double-blinded study, my ride distribution is not even. Instead, every morning I use a weighted random selection process. Each mode gets a likelihood to be picked based on it’s share of prior commutes modified by its score performance.

L(‘Bus’) = # Bus rides / all commutes * (Average Bus Score / Average Score)
  • eg: This morning as I write, I have taken UberX 27 times out of 200 commutes (13.5% of all rides). UberX’s combined score is 71.6, while the weighted average is 80.2 (UberX slightly underperfoms on time-cost: a wicked fast average time of 17 minutes but a high real cost average of $17.07). So:
(27 / 200) * (71.6 / 80.2) = 0.12 (12%)

Thus this morning, I had a 1-in-8 shot of getting UberX.

Why not just choose the best each day? I’m hedging against change. I’m willing to pay a premium for information collection, on the chance it reveals a better return. It’s already started paying off: in the past year Scoot negotiated with the city for street parking, meaning I can now drop my Scoot along designated curbs rather than in specific garages. This has greatly shortened my commute and improving Scoot’s score.

That’s also why I randomly pick (score-blind) 10% of the time, it gives new comers and bad scorers a chance to get picked and re-evaluated.

The Results

Download the trip data

(RIP Sidecar)

So, is it working?

The things I care about are my inputs: Time, Cost and Comfort.

Start with time

blue dots: individual ride

red line: 10-ride trailing average

green line: cumulative average

Effect on duration: minimal to none. Around ride 25 the average settled to 30 minutes and has effectively not changed since. Currently I’m at 29.74 minutes. My smoothed average keeps bouncing around the cumulative average, suggesting it’s just Brownian motion around this number.

What about cost?

Effect on cost: moderate. There seem to be three periods here: for the first 70 rides I gradually brought cost down from $12 to $8.90. Then for the next 30 rides a string of high-cost commutes yank the average back up to $10.70 (it looks like I took fewer Uber Pool/Lyft Line and more UberX/Lyft). Since then the smoothed view (red) is well below the cumulative average (green), so we’re back to tugging the average down (Muni and Scoot have started to gain share). I’m now at $9.26, a roughly 25% drop since starting.


Effect on comfort: minimal. The cumulative average drops I started around 4.0 and now am around 3.6. The volatility looks high in the smoothed average, but looks to keep nudging me down. Unlike cost or duration, comfort is a metric I want going up!

So in effect, after a year I’m getting a lower-priced commute at slightly deteriorating comfort levels and taking the same amount of time.

Who’s Winning?

Most people don’t care if I’m getting to work faster, cheaper or in greater comfort. Instead what the most common question is: “which method is the best?” “The best on which metric?” is usually my reply (which might be why people hate working with data analysts).

Aside from straight up time, cost and comfort, another metric I could test out is a wins above replacement approach. How much am I paying to shave a minute off my commute by going to the next fastest option. So Walking cost me $0, and the next fastest mode is Muni at $3.19 average, which saves me 5.3 minutes. So $3.19/5.3 = $0.6 per minute saved. Shaving another 2.6 minutes off by taking Scoot costs me an extra $1.41 or $0.55 per marginal minute.

It quickly becomes clear that some modes are just terrible: anything with a negative win above replacement is a mode that saves me time AND money (Yellowcab costs $15 less than Curb and saves me seven minutes).

I could also look at wins above replacement against a common benchmark: walking. Again, I see where the value opportunities are and can adjust based on how much I want to spend. Muni, Scoot, Flywheel and UberX are all in the ~$0.60 per minute premium; so (comfort aside) these are all equivalent modes and it’s just a question of balancing how much time I want to “buy”.

The winner for most efficient minute-to-dollar exchange is Uber Pool, which gives me a minute back for every $0.27 I spend! Lyft Line isn’t too far behind ($0.31), then there’s a big group at the $0.50-$0.60 options (Sidecar, Scoot, Flywheel, UberX, Muni), a big step up to Lyft ($0.80), another step to Yellowcab ($1.14) followed by a long ride out to Curb ($3.70)!

The tiers of value can also be visualized by graphing cost vs time

Each ride is plotted according to it’s cost (x) and minutes (y). Large dots sit at the average for the type, sized relative to the number of times taken.

I’m going to start thinking of the modes as falling in four categories:

  • Cheap: Walking, Scoot, Muni
  • Value: UberPool, Lyft Line
  • Fast: Flywheel, UberX
  • Just Plain Bad: Lyft, Sidecar, Yellowcab, Curb

A few notes on some interesting outliers:

  • Longest ride: 90 minutes (8:19–9:49) on Muni on July 28th. It cost me $25.09 and scored a comfort of 1. I have no idea what happened that day, but likely I got stuck waiting for a very delayed bus and just took an UberX instead (attributing the cost to Muni).
  • Shortest ride: 12 minutes (9:00–9:12) on UberX on October 14th. It costs $16.23 and scored a comfort of 5.
  • Priciest ride: $39.76 on UberX On September 17th. It took 18 minutes (8:48–9:06) and got a comfort of 4. My guess is that was during Dreamforce (big, city-destroying conference) and I foolishly left at rush hour.
  • Cheapest ride: seven-way tie of $0. Six times I walked, one time I took Scoot and had credit. Each took between 45 and 61 minutes and comfort scores varied 1–4.

What’s next?

I’m looking forward to trying out new modes as they come online. I’ve added Luxor App but it hasn’t yet randomly been picked (it has a 0.91% chance every day). I’m also looking forward to Chariot and Bay Area Bike Share expanding along my commute. Some friends have pointed out I could buy a bike, but that puts a high capital cost on a mode that might not be great (should I amortize? assign all cost to the first ride?). Getaround, Turo and other car shares aren’t really set up for one-way commuting. Any other suggestions?

Aside from new methods of travel, there’re new methods to score.

Euclidean distance is probably the wrong way to measure time+cost. Curb, for example, cost $33 and took 39 minutes (both bad), but it gets a time-cost of only $35.44, if I straight added ($33.33 + 39 minutes * $0.31 per minute) I’d have a much worse $45.42. Euclidean distance is meant to show that by going x distance you saved yourself going a+b distance; which is not the case here at all. By spending time and money, I saved neither!

But forget Euclidean distance. Perhaps just looking at my time/dollar exchange rate is how I should grade a method. $0.27 per minute-saved (Uber Pool) is my best rate, so if I’m in the business of trading money for time, that’s the best value. But, like marketing budgets, I can only put so much money in before diminished returns. To save myself say 47 minutes (off a 48 minute walking commute) I cannot simply offer Uber Pool $12.69 (47 * $0.27); the only existing method is relocating to where I work, pricey indeed. But I suppose to save myself 47 minutes over the fewest commutes, the best option is still Uber Pool.

Then what of comfort? Rather than an arbitrary weighting process, I need another exchange. Is 5-minutes of lowest comfort equivalent to 25 minutes of highest comfort? I suspect there should be some sort of weighting at the time level. eg I’d rather spend 2 minutes sitting on an empty bus reading than 1 minute navigating a scooter in the pouring rain. So uncomfortable minutes get a 2x multiplier penalty. What’s the right multiplier, 3x, 5x?

Ultimately the question comes down to: what am I trying to optimize for? I want to get to work as quickly, cheaply and comfortably as I can. Optimizing along three dimensions is hard, so I think consciously understanding the tradeoffs to flatten along one derived metric will give me a better apples-to-apples comparison. I think I’ll switch and adjust minutes commuting based on comfort and then try to minimize my dollars-per-comfort-adjusted-minute-saved (DpCAMS? that’s a terrible name for a metric).

Time to go collect more data and see if this works!

Like what you read? Give Scott Breudecheck a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.