Trips into the congestion zone
Count taxi and Uber/Lyft trips into Manhattan's congestion relief zone before and after pricing began on January 5, 2025.
Congestion pricing started on January 5, 2025, for vehicles entering Manhattan below 60 St. Taxis and app cars pay a per-trip fee there, recorded as cbd_congestion_fee. Here we use that fee to find the zone, then count trips a year apart.
This is a short version of our taxi and app study, which adds speeds and intervals.
Step 1: find the zone
Section titled “Step 1: find the zone”The TLC’s 263 taxi zones don’t line up with 60 St, but the fee tells us which zones are inside. A trip that starts and ends in the same zone inside the area should nearly always carry the fee; one outside, almost never.
ATTACH 'https://data.transitlab.nyc/v1/transitlab.duckdb' AS transitlab (READ_ONLY);
CREATE TABLE cbd ASSELECT pickup_zone_id AS zone, any_value(pickup_zone) AS nameFROM transitlab.taxi_yellow_tripsWHERE pickup_datetime >= '2025-03-01' AND pickup_datetime < '2025-04-01' AND pickup_zone_id = dropoff_zone_idGROUP BY zoneHAVING count(*) >= 100 AND avg((cbd_congestion_fee > 0)::INT) >= 0.6;
SELECT count(*) FROM cbd; -- about 37 zonesZones that straddle 60 St land between 5% and 60%. They are left out here, so trips to Central Park or Lenox Hill count as neither in nor out.
Step 2: count trips a year apart
Section titled “Step 2: count trips a year apart”WITH trips AS ( SELECT 'yellow' AS kind, pickup_datetime AS t, pickup_zone_id AS pu, dropoff_zone_id AS dz FROM transitlab.taxi_yellow_trips WHERE pickup_datetime >= '2024-02-01' UNION ALL SELECT 'uber/lyft', pickup_datetime, pickup_zone_id, dropoff_zone_id FROM transitlab.fhv_trips WHERE pickup_datetime >= '2024-02-01')SELECT kind, year(t) AS year, count(*) FILTER (WHERE pu IN (SELECT zone FROM cbd) OR dz IN (SELECT zone FROM cbd)) / count(DISTINCT t::DATE) AS touching_zone_per_day, count(*) FILTER (WHERE pu NOT IN (SELECT zone FROM cbd) AND dz NOT IN (SELECT zone FROM cbd)) / count(DISTINCT t::DATE) AS elsewhere_per_dayFROM tripsWHERE month(t) BETWEEN 2 AND 8 -- the same months each year AND dayofweek(t) BETWEEN 1 AND 5 -- weekdays AND hour(t) BETWEEN 6 AND 19 -- 6 am to 8 pmGROUP BY kind, yearORDER BY kind, year;January is left out: pricing began partway through it. Comparing the same months each year keeps the seasons out of the answer.
Reading it
Section titled “Reading it”Compare the change in touching_zone_per_day with the change in elsewhere_per_day. Trips can rise or fall citywide for many reasons (fares, the weather, the economy). What pricing might explain is the gap between the two.
This query reads a lot: two years of the two largest tables. Expect a few minutes on a laptop with a good connection. To go faster, keep just the columns used here in a local table first (see Keep queries fast).
Going further
Section titled “Going further”- Speeds. Compare
trip_miles / trip_minutesfor trips inside the zone with trips entirely above 60 St. The study does this and holds each zone pair fixed. - Buses. Congestion pricing: buses uses the MTA’s bus speeds inside and outside the zone.