Skip to content
Docs

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.

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 AS
SELECT pickup_zone_id AS zone, any_value(pickup_zone) AS name
FROM transitlab.taxi_yellow_trips
WHERE pickup_datetime >= '2025-03-01' AND pickup_datetime < '2025-04-01'
AND pickup_zone_id = dropoff_zone_id
GROUP BY zone
HAVING count(*) >= 100 AND avg((cbd_congestion_fee > 0)::INT) >= 0.6;
SELECT count(*) FROM cbd; -- about 37 zones

Zones 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.

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_day
FROM trips
WHERE 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 pm
GROUP BY kind, year
ORDER 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.

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).

  • Speeds. Compare trip_miles / trip_minutes for 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.