CHANGE of Yellow Taxi Ridership

Yuan Hua
Data Mining the City
9 min readOct 20, 2017

Is subway reducing the ridership of yellow taxi?

Subways, as a main component of the public transit system in New York, is anticipated to reduce the ridership of taxis. After almost 100 years waiting, the long delayed Second Avenue Subway Q line finally opened to the public on January 1st, 2017, extending from 63 St to 96 St. This improves the public transit accessibility on the Upper East Side of Manhattan, and it might also influence the subway system in NY as a whole. This project looks into the yellow taxi ridership before and after the launch of the Q-extension.

Neighborhood residents, Pam and Ben Miller wait at the entrance of the 96th Street and Second Avenue Q train station to ride the inaugural Second Avenue Q train. January 1st, 2017. (source: https://www.theverge.com/2017/1/2/14145396/second-avenue-subway-nyc-mta-cuomo-photos)
Change of Yellow Taxi Trip Counts at City-Level between Dec 2016 and Jan 2017

At the city level, in most TLC taxi zones, both trip counts of pick-up and drop-off drops from Dec 2016 to Jan 2017. This might partially resulted from the seasonal change as the tourism cools. However, we can still notice the huge decrease in the taxi zones adjacent to the new subway stations.

Zooming into the seven taxi zones around the Q-extension stations, the counts of pickups went up during Christmas holiday in December, and then dropped in January and February, which seems to show the impact of subway launching as expected. However, the ridership reversed in March. Further research has to be conducted to explain this phenomenon.

Data Source

The data of yellow taxi ridership and taxi zones is provided by NYC Taxi & Limousine Commission accessed through http://www.nyc.gov/html/tlc/html/about/trip_record_data.shtml.

Code

The codes for the bar chart diagram:

import csvdef setup():
size(1400, 480)
# city-level data
with open('/Users/hy/Documents/SEMESTER 3/DataMining/MidtermProject/data/combine_dec_jan_city.csv') as f:
reader = csv.reader(f)
header = reader.next() # Skip the header row

# define new names
global city_PU_before
city_PU_before = []
global city_DO_before
city_DO_before = []
global city_PU_after
city_PU_after = []
global city_DO_after
city_DO_after = []
global locations
locations = []
global boroughs
boroughs = []
global PU_changes
PU_changes = []
global DO_changes
DO_changes = []

# rename variables to match the global variables defined above
for row in reader:
city_PU_before_count = float(row[1])
city_PU_before.append(city_PU_before_count)
city_PU_after_count = float(row[2])
city_PU_after.append(city_PU_after_count)
city_DO_before_count = float(row[3])
city_DO_before.append(city_DO_before_count)
city_DO_after_count = float(row[4])
city_DO_after.append(city_DO_after_count)
location = row[5]
locations.append(location)
borough = row[6]
boroughs.append(borough)
PU_change = float(row[7])
PU_changes.append(PU_change)
DO_change = float(row[8])
DO_changes.append(DO_change)
def draw():
background(0)
stroke(0)

# load image
global img
img = loadImage('YellowTaxi.png')

# bar charts for trip counts of the whole city
scalar = 8
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
g = 0
h = 0

for city_PU_count_before in city_PU_before:
if mouseX <= a or mouseX > a+6:
fill(153, 153, 0)
rect(a, 260, 3, -log(city_PU_count_before)*scalar)
else:
fill(230, 92, 0)
rect(a, 260, 3, -log(city_PU_count_before)*scalar)
# showing text in information text frame
fill(153, 153, 0)
textSize(12)
text(int(city_PU_count_before), 140, 412)
a = a+6

for city_PU_count_after in city_PU_after:
if mouseX <= b or mouseX > b+6:
fill(255, 255, 128)
rect(b+3, 260, 3, -log(city_PU_count_after)*scalar)
else:
fill(230, 92, 0)
rect(b+3, 260, 3, -log(city_PU_count_after)*scalar)
# showing text in information text frame
fill(255, 255, 128)
textSize(12)
text(int(city_PU_count_after), 305, 412)
b = b+6

for city_DO_count_before in city_DO_before:
if mouseX <= c or mouseX > c+6:
fill(0, 85, 128)
rect(c, 260, 3, log(city_DO_count_before)*scalar)
else:
fill(0, 153, 0)
rect(c, 260, 3, log(city_DO_count_before)*scalar)
# showing text in information text frame
textSize(12)
fill(0, 85, 128)
text(int(city_DO_count_before), 145, 427)
c = c+6

for city_DO_count_after in city_DO_after:
if mouseX <= d or mouseX > d+6:
fill(179, 230, 255)
rect(d+3, 260, 3, log(city_DO_count_after)*scalar)
else:
fill(0, 153, 0)
rect(d+3, 260, 3, log(city_DO_count_after)*scalar)
# showing text in information text frame
fill(179, 230, 255)
textSize(12)
text(int(city_DO_count_after), 315, 427)
d = d+6

for location in locations:
if mouseX >= e and mouseX < e+6:
textSize(12)
if location == 'East Harlem South' or location == 'Lenox Hill West' or location == 'Lenox Hill East' or location == 'Upper East Side South' or location == 'Upper East Side North' or location == 'Yorkville West' or location == 'Yorkville East':
fill(255)
text('TAXI ZONE: ' + location + ', which is adjacent to the Q-Extension stations', 20, 395)
else:
fill(255)
text('TAXI ZONE: ' + location, 20, 395)
image(img, e-20, 230, 50, 30)
e = e+6

for borough in boroughs:
if mouseX >= f and mouseX < f+6:
textSize(12)
fill(255)
text('BOROUGH: ' + borough, 20, 380)
f = f+6

for PU_change in PU_changes:
if mouseX >= g and mouseX < g+6:
textSize(12)
fill(255)
if PU_change < 0:
text('CHANGE of PickUp: DECREASE', 20, 445)
elif PU_change == 0:
text('CHANGE of PickUp: NO CHANGE', 20, 445)
else:
text('CHANGE of PickUp: INCREASE', 20, 445)
g = g+6

for DO_change in DO_changes:
if mouseX >= h and mouseX < h+6:
textSize(12)
fill(255)
if DO_change < 0:
text('CHANGE of GropOff: DECREASE', 20, 460)
elif DO_change == 0:
text('CHANGE of GropOff: NO CHANGE', 20, 460)
else:
text('CHANGE of GropOff: INCREASE', 20, 460)
h = h+6

# title
fill(255)
textSize(18)
text("CHANGE of Yellow Taxi Trip Counts between Dec 2016 and Jan 2017", 20, 30)
textSize(14)
text("by TLC Taxi Zone", 20, 50)

# legend
fill(153, 153, 0) # before
rect(80, 90, 8,8)
fill(255, 255, 128) # after
rect(150, 90, 8,8)
fill(255)
textSize(10)
text("Pick Up", 20, 83)
text("Dec 2016", 20, 98)
text("Jan 2017", 95, 98)

fill(0, 85, 128) # before
rect(80, 125, 8,8)
fill(179, 230, 255) # after
rect(150, 125, 8,8)
fill(255)
textSize(10)
text("Drop Off", 20, 118)
text("Dec 2016", 20, 133)
text("Jan 2017", 95, 133)

# basic information text
fill(255)
textSize(12)
text("Count of pickups is in Dec 2016 VS. in Jan 2017.", 20, 412)
textSize(12)
text("Count of dropoffs is in Dec 2016 VS. in Jan 2017.", 20, 427)

The codes for the SlippyMapper:

import spatialpixel.mapping.slippymapper as slippymapper
import csv
def setup():
size(800, 800, P2D)
# subway station basemap
global nyc
nyc = slippymapper.SlippyMapper(40.785, -73.959, 14, 'carto-dark', width, height)
# function to provide to addMarker()
def subway_marker(x,y,marker):
marker.noStroke()
marker.fill(170)
marker.ellipse(x,y,7,7)
def target_subway_marker(x,y,marker):
marker.noStroke()
marker.fill(255,0,0)
marker.ellipse(x,y,10,10)
with open('/Users/hy/Documents/SEMESTER 3/DataMining/MidtermProject/data/SubwayStations.csv') as f:
reader = csv.reader(f)
header = reader.next()
for row in reader:
id = row[0]
station_name = row[1]
latitude = row[3]
longitude = row[2]
nyc.addMarker(float(latitude), float(longitude),subway_marker)

# target stations
nyc.addMarker(40.76880251,-73.95836179,target_subway_marker)
nyc.addMarker(40.77786104,-73.95177091,target_subway_marker)
nyc.addMarker(40.78423665,-73.94706602,target_subway_marker)
nyc.render()

# trip data
with open('/Users/hy/Documents/SEMESTER 3/DataMining/MidtermProject/data/combine_trip_oct_mar.csv') as f:
reader = csv.reader(f)
header = reader.next()
print reader
# define new names
global PickUpCount
PickUpCount = {}
global DropOffCount
DropOffCount = {}
global zones
zones = ['zone75', 'zone140', 'zone141', 'zone236', 'zone237', 'zone262', 'zone263']

for row in reader:
key = row[0]
PickUpCount[key] = row[1:7]
DropOffCount[key] = row[7:]
#print PickUpCount
#print DropOffCount
#print PickUpCount['zone75'][1]
def draw():
background(255)
nyc.draw()
# load image
global img
img = loadImage('YellowTaxi.png')
global arrow_up
arrow_up = loadImage('arrow-01.png')
global arrow_down
arrow_down = loadImage('arrow-02.png')
global arrow_nochange
arrow_nochange = loadImage('arrow-03.png')

# draw boundaries of taxi zones
stroke(15)
strokeWeight(3)
strokeJoin(ROUND)
fill(170,170,170,65)
# zone 237
quad(420,565,345,525,236,720,311,760)
# zone 141
quad(474,595,420,565,311,760,365,790)
# zone 140
quad(535,630,474,595,365,790,400,810)
# zone 236
quad(514,397,438,355,345,525,420,565)
# zone 263
quad(566,427,514,397,420,565,474,595)
# zone 262
beginShape()
vertex(575,432)
vertex(566,427)
vertex(474,595)
vertex(535,630)
vertex(593,545)
endShape(CLOSE)
# zone 75
beginShape()
vertex(668,305)
vertex(513,218)
vertex(438,355)
vertex(575,432)
vertex(640,370)
endShape(CLOSE)
# bar charts for trip counts of taxi zones
PUscalar = -0.0005
DOscalar = 0.0005
x = 0
y = 0
z = 0

#for zone in zones:
# for PUCount in PickUpCount[zone]:
# stroke(0)
# strokeWeight(1)
# fill(255)
# rect(x, height/2, 5, float(PUCount)*PUscalar)
# x = x+5
# x = x+5

# title
fill(255)
textSize(18)
text('CHANGE of Yellow Taxi Pickups around Q-Extension Stations', 15,30)
textSize(14)
text('From Oct 2016 To Mar 2017', 15,45)
text('by TLC Taxi Zone', 15,60)
# month button for showing
stroke(255)
strokeWeight(1)
fill(255)
line(20,80,20,330)
strokeWeight(2)
line(15,80,30,80)
line(15,130,30,130)
line(15,180,30,180)
line(15,230,30,230)
line(15,280,30,280)
line(15,330,30,330)
textSize(10)
text('Nov 2016', 40,110)
text('Dec 2016', 40,160)
text('Jan 2016: LAUNCH OF Q-EXTENSION on Jan 1', 40,210)
text('Feb 2017', 40,260)
text('Mar 2017', 40,310)
# Oct - Nov
if mouseX>=10 and mouseX<150 and mouseY>=80 and mouseY<130:
# zone 75
if PickUpCount['zone75'][0]>PickUpCount['zone75'][1]:
image(arrow_down, 530, 300, 40,40)
elif PickUpCount['zone75'][0]==PickUpCount['zone75'][1]:
image(arrow_nochange, 530, 300, 40,40)
else:
image(arrow_up, 530, 300, 40,40)
# zone 140
if PickUpCount['zone140'][0]>PickUpCount['zone140'][1]:
image(arrow_down, 420, 700, 40,40)
elif PickUpCount['zone140'][0]==PickUpCount['zone140'][1]:
image(arrow_nochange, 420, 700, 40,40)
else:
image(arrow_up, 420, 700, 40,40)
# zone 141
if PickUpCount['zone141'][0]>PickUpCount['zone141'][1]:
image(arrow_down, 370, 670, 40,40)
elif PickUpCount['zone141'][0]==PickUpCount['zone141'][1]:
image(arrow_nochange, 370, 670, 40,40)
else:
image(arrow_up, 370, 670, 40,40)
# zone 236
if PickUpCount['zone236'][0]>PickUpCount['zone236'][1]:
image(arrow_down, 410, 440, 40,40)
elif PickUpCount['zone236'][0]==PickUpCount['zone236'][1]:
image(arrow_nochange, 410, 440, 40,40)
else:
image(arrow_up, 410, 440, 40,40)
# zone 237
if PickUpCount['zone237'][0]>PickUpCount['zone237'][1]:
image(arrow_down, 310, 620, 40,40)
elif PickUpCount['zone237'][0]==PickUpCount['zone237'][1]:
image(arrow_nochange, 310, 620, 40,40)
else:
image(arrow_up, 310, 620, 40,40)
# zone 262
if PickUpCount['zone262'][0]>PickUpCount['zone262'][1]:
image(arrow_down, 480, 470, 40,40)
elif PickUpCount['zone262'][0]==PickUpCount['zone262'][1]:
image(arrow_nochange, 480, 470, 40,40)
else:
image(arrow_up, 480, 470, 40,40)
# zone 263
if PickUpCount['zone263'][1]>PickUpCount['zone263'][1]:
image(arrow_down, 530, 520, 40,40)
elif PickUpCount['zone263'][1]==PickUpCount['zone263'][1]:
image(arrow_nochange, 530, 520, 40,40)
else:
image(arrow_up, 530, 520, 40,40)

# Nov - Dec
if mouseX>=10 and mouseX<150 and mouseY>=130 and mouseY<180:
# zone 75
if PickUpCount['zone75'][1]>PickUpCount['zone75'][2]:
image(arrow_down, 530, 300, 40,40)
elif PickUpCount['zone75'][1]==PickUpCount['zone75'][2]:
image(arrow_nochange, 530, 300, 40,40)
else:
image(arrow_up, 530, 300, 40,40)
# zone 140
if PickUpCount['zone140'][1]>PickUpCount['zone140'][2]:
image(arrow_down, 420, 700, 40,40)
elif PickUpCount['zone140'][1]==PickUpCount['zone140'][2]:
image(arrow_nochange, 420, 700, 40,40)
else:
image(arrow_up, 420, 700, 40,40)
# zone 141
if PickUpCount['zone141'][1]>PickUpCount['zone141'][2]:
image(arrow_down, 370, 670, 40,40)
elif PickUpCount['zone141'][1]==PickUpCount['zone141'][2]:
image(arrow_nochange, 370, 670, 40,40)
else:
image(arrow_up, 370, 670, 40,40)
# zone 236
if PickUpCount['zone236'][1]>PickUpCount['zone236'][2]:
image(arrow_down, 410, 440, 40,40)
elif PickUpCount['zone236'][1]==PickUpCount['zone236'][2]:
image(arrow_nochange, 410, 440, 40,40)
else:
image(arrow_up, 410, 440, 40,40)
# zone 237
if PickUpCount['zone237'][1]>PickUpCount['zone237'][2]:
image(arrow_down, 310, 620, 40,40)
elif PickUpCount['zone237'][1]==PickUpCount['zone237'][2]:
image(arrow_nochange, 310, 620, 40,40)
else:
image(arrow_up, 310, 620, 40,40)
# zone 262
if PickUpCount['zone262'][1]>PickUpCount['zone262'][2]:
image(arrow_down, 480, 470, 40,40)
elif PickUpCount['zone262'][1]==PickUpCount['zone262'][2]:
image(arrow_nochange, 480, 470, 40,40)
else:
image(arrow_up, 480, 470, 40,40)
# zone 263
if PickUpCount['zone263'][1]>PickUpCount['zone263'][2]:
image(arrow_down, 530, 520, 40,40)
elif PickUpCount['zone263'][1]==PickUpCount['zone263'][2]:
image(arrow_nochange, 530, 520, 40,40)
else:
image(arrow_up, 530, 520, 40,40)

# Dec - Jan
if mouseX>=10 and mouseX<150 and mouseY>=180 and mouseY<230:
# zone 75
if PickUpCount['zone75'][2]>PickUpCount['zone75'][3]:
image(arrow_down, 530, 300, 40,40)
elif PickUpCount['zone75'][2]==PickUpCount['zone75'][3]:
image(arrow_nochange, 530, 300, 40,40)
else:
image(arrow_up, 530, 300, 40,40)
# zone 140
if PickUpCount['zone140'][2]>PickUpCount['zone140'][3]:
image(arrow_down, 420, 700, 40,40)
elif PickUpCount['zone140'][2]==PickUpCount['zone140'][3]:
image(arrow_nochange, 420, 700, 40,40)
else:
image(arrow_up, 420, 700, 40,40)
# zone 141
if PickUpCount['zone141'][2]>PickUpCount['zone141'][3]:
image(arrow_down, 370, 670, 40,40)
elif PickUpCount['zone141'][2]==PickUpCount['zone141'][3]:
image(arrow_nochange, 370, 670, 40,40)
else:
image(arrow_up, 370, 670, 40,40)
# zone 236
if PickUpCount['zone236'][2]>PickUpCount['zone236'][3]:
image(arrow_down, 410, 440, 40,40)
elif PickUpCount['zone236'][2]==PickUpCount['zone236'][3]:
image(arrow_nochange, 410, 440, 40,40)
else:
image(arrow_up, 410, 440, 40,40)
# zone 237
if PickUpCount['zone237'][2]>PickUpCount['zone237'][3]:
image(arrow_down, 310, 620, 40,40)
elif PickUpCount['zone237'][2]==PickUpCount['zone237'][3]:
image(arrow_nochange, 310, 620, 40,40)
else:
image(arrow_up, 310, 620, 40,40)
# zone 262
if PickUpCount['zone262'][2]>PickUpCount['zone262'][3]:
image(arrow_down, 480, 470, 40,40)
elif PickUpCount['zone262'][2]==PickUpCount['zone262'][3]:
image(arrow_nochange, 480, 470, 40,40)
else:
image(arrow_up, 480, 470, 40,40)
if PickUpCount['zone263'][2]>PickUpCount['zone263'][3]:
image(arrow_down, 530, 520, 40,40)
elif PickUpCount['zone263'][2]==PickUpCount['zone263'][3]:
image(arrow_nochange, 530, 520, 40,40)
else:
image(arrow_up, 530, 520, 40,40)

# Jan - Feb
if mouseX>=10 and mouseX<150 and mouseY>=230 and mouseY<280:
# zone 75
if PickUpCount['zone75'][3]>PickUpCount['zone75'][4]:
image(arrow_down, 530, 300, 40,40)
elif PickUpCount['zone75'][3]==PickUpCount['zone75'][4]:
image(arrow_nochange, 530, 300, 40,40)
else:
image(arrow_up, 530, 300, 40,40)
# zone 140
if PickUpCount['zone140'][3]>PickUpCount['zone140'][4]:
image(arrow_down, 420, 700, 40,40)
elif PickUpCount['zone140'][3]==PickUpCount['zone140'][4]:
image(arrow_nochange, 420, 700, 40,40)
else:
image(arrow_up, 420, 700, 40,40)
# zone 141
if PickUpCount['zone141'][3]>PickUpCount['zone141'][4]:
image(arrow_down, 370, 670, 40,40)
elif PickUpCount['zone141'][3]==PickUpCount['zone141'][4]:
image(arrow_nochange, 370, 670, 40,40)
else:
image(arrow_up, 370, 670, 40,40)
# zone 236
if PickUpCount['zone236'][3]>PickUpCount['zone236'][4]:
image(arrow_down, 410, 440, 40,40)
elif PickUpCount['zone236'][3]==PickUpCount['zone236'][4]:
image(arrow_nochange, 410, 440, 40,40)
else:
image(arrow_up, 410, 440, 40,40)
# zone 237
if PickUpCount['zone237'][3]>PickUpCount['zone237'][4]:
image(arrow_down, 310, 620, 40,40)
elif PickUpCount['zone237'][3]==PickUpCount['zone237'][4]:
image(arrow_nochange, 310, 620, 40,40)
else:
image(arrow_up, 310, 620, 40,40)
# zone 262
if PickUpCount['zone262'][3]>PickUpCount['zone262'][4]:
image(arrow_down, 480, 470, 40,40)
elif PickUpCount['zone262'][3]==PickUpCount['zone262'][4]:
image(arrow_nochange, 480, 470, 40,40)
else:
image(arrow_up, 480, 470, 40,40)
# zone 263
if PickUpCount['zone263'][3]>PickUpCount['zone263'][4]:
image(arrow_down, 530, 520, 40,40)
elif PickUpCount['zone263'][3]==PickUpCount['zone263'][4]:
image(arrow_nochange, 530, 520, 40,40)
else:
image(arrow_up, 530, 520, 40,40)

# Feb - Mar
if mouseX>=10 and mouseX<150 and mouseY>280 and mouseY<330:
# zone 75
if PickUpCount['zone75'][4]>PickUpCount['zone75'][5]:
image(arrow_down, 530, 300, 40,40)
elif PickUpCount['zone75'][4]==PickUpCount['zone75'][5]:
image(arrow_nochange, 530, 300, 40,40)
else:
image(arrow_up, 530, 300, 40,40)
# zone 140
if PickUpCount['zone140'][4]>PickUpCount['zone140'][5]:
image(arrow_down, 420, 700, 40,40)
elif PickUpCount['zone140'][4]==PickUpCount['zone140'][5]:
image(arrow_nochange, 420, 700, 40,40)
else:
image(arrow_up, 420, 700, 40,40)
# zone 141
if PickUpCount['zone141'][4]>PickUpCount['zone141'][5]:
image(arrow_down, 370, 670, 40,40)
elif PickUpCount['zone141'][4]==PickUpCount['zone141'][5]:
image(arrow_nochange, 370, 670, 40,40)
else:
image(arrow_up, 370, 670, 40,40)
# zone 236
if PickUpCount['zone236'][4]>PickUpCount['zone236'][5]:
image(arrow_down, 410, 440, 40,40)
elif PickUpCount['zone236'][4]==PickUpCount['zone236'][5]:
image(arrow_nochange, 410, 440, 40,40)
else:
image(arrow_up, 410, 440, 40,40)
# zone 237
if PickUpCount['zone237'][4]>PickUpCount['zone237'][5]:
image(arrow_down, 310, 620, 40,40)
elif PickUpCount['zone237'][4]==PickUpCount['zone237'][5]:
image(arrow_nochange, 310, 620, 40,40)
else:
image(arrow_up, 310, 620, 40,40)
# zone 262
if PickUpCount['zone262'][4]>PickUpCount['zone262'][5]:
image(arrow_down, 480, 470, 40,40)
elif PickUpCount['zone262'][4]==PickUpCount['zone262'][5]:
image(arrow_nochange, 480, 470, 40,40)
else:
image(arrow_up, 480, 470, 40,40)
# zone 263
if PickUpCount['zone263'][4]>PickUpCount['zone263'][5]:
image(arrow_down, 530, 520, 40,40)
elif PickUpCount['zone263'][4]==PickUpCount['zone263'][5]:
image(arrow_nochange, 530, 520, 40,40)
else:
image(arrow_up, 530, 520, 40,40)

--

--