SparkyData

NYC Subway Crime Rates and Ridership, 1998–2026

NYPD subway complaints by month, day, hour and station since 2014, with ridership where available; transit-system felonies since fiscal 1998

No synthetic records. Complaints and arrests come from NYPD records; fare-evasion shares are MTA estimates. Monthly paid rides before March 2020 are modelled from official yearly totals, and total entries are estimated throughout. Check paid_rides_method and data_dictionary.csv before using a rate.

Records
Administrative records
Covers
Subway complaints by month, day, hour and station, January 2014 to June 2026 (June incomplete); paid rides by month July 1997 to September 2026, by day from March 2020, by station from February 2017; Transit arrests January 2014 to June 2026; transit-system major felonies by fiscal year 1998 to 2026.
Place
New York City subway (NYPD premises 'TRANSIT - NYC SUBWAY'), by station complex; the fiscal series counts the whole transit system, and the context file the whole city and its buses
Version
2.0,
Licence
Mixed: CC BY 4.0 for what we added; the government's records under their publishers' terms; code MIT (LICENSE.md)
Built for
Per subway ride, major felonies fell for thirty years. Felony assault broke from the fall. (version 1.0)

This dataset pairs complaints recorded in the New York City subway by the New York City Police Department (NYPD), January 2014 to June 2026, with ridership from the Metropolitan Transportation Authority (MTA), so that complaint counts can be compared as rates per million paid rides and per million estimated entries, paid or not. The complaint files cover months, days, hours, stations and victim groups, and subway_complaint_records.csv has one row per complaint, with categorical fields and gaps kept from the source. A separate series covers major felonies across the transit system back to fiscal 1998. Start with subway_crime_monthly.csv: one row per month, with counts, rides and rates already combined.

The story in these files

Every few months a headline asks whether the subway is safe, and most answers count crimes. A count alone cannot say whether a ride became riskier. The subway carried 1.7 billion paid rides in 2019 and 640 million in 2020, so the same number of crimes meant something very different in the two years. To ask about risk you need two things side by side: what happened, and how many people were there when it happened.

This dataset puts them side by side: the NYPD's records of complaints in the subway, with the codes that tell an assault on a police officer from any other assault or a pickpocketing from a phone taken from a sleeping rider, and the MTA's counts of entries to the system. Around them sits the context a careful reader asks for next: recorded crime across the whole city and on its buses, arrests by transit police, the shelter census, Central Park's weather, and a dated list of the laws, policing announcements and service changes that help explain changes in the series.

Three tensions run through the files, and they are what make them worth more than a table of rates. The first is the denominator, the number of rides or entries a complaint count is divided by: the MTA counts paid rides, and the share of people who do not pay more than doubled after 2019, so the choice of denominator alone moves a comparison. The second is that a complaint records police work as well as crime; theft of services, the offence that covers fare evasion, shows how far the two can part. The third is that some numbers here are counted and some are modelled, and the monthly paid rides before March 2020 are the largest modelled piece; the MTA's station counts, summed, now let you test that model month by month. The monthly table carries the method and reporting flags, and the finer files carry the reporting flags of their month or year, so the distinctions travel with the data.

Start here

Open subway_crime_monthly.csv first. Each row is a month, by the month the crime began, and it already holds the rates, so no join is needed to start. Compare *_per_m_paid (per million paid rides) with *_per_m_entries (per million estimated entries, paid or not). For a recent comparison, use January to May rather than June 2026, which is still filling in, and remember that complete marks a reporting window, not a final count. The example below works out the January-to-May felony-assault rate for 2019, 2025 and 2026 both ways.

import pandas as pd

m = pd.read_csv("subway_crime_monthly.csv", dtype={"month": "string", "complete": "boolean",
                "paid_rides": "Int64", "entries_est": "Int64",
                "late_reports_all": "Int64", "late_reports_six_major": "Int64"})

# January-May rate for each year: total complaints divided by total rides or entries,
# not the mean of monthly rates; a window with any missing entries stays missing
w = m[m["month"].str[5:].isin(["01", "02", "03", "04", "05"])]
g = w.groupby("year").agg(felony_assault=("felony_assault", "sum"), paid=("paid_rides", "sum"),
                          entries=("entries_est", lambda x: x.sum() if x.notna().all() else pd.NA))
g["per_m_paid"] = 1e6 * g["felony_assault"] / g["paid"]
g["per_m_entries"] = 1e6 * g["felony_assault"] / g["entries"].astype("Float64")
print(g.loc[[2019, 2025, 2026]].round(2))

It prints:

      felony_assault       paid    entries  per_m_paid  per_m_entries
year
2019             157  702461957  730969778        0.22           0.21
2025             267  523745387  580922734        0.51           0.46
2026             272  537074361  599623313        0.51           0.45

How the files join:

  • Join subway_ridership_monthly.csv and city_context_monthly.csv to subway_crime_monthly.csv on month: one row each per month, January 2014 to June 2026.
  • For subway_crime_daily.csv and subway_crime_by_hour.csv, first add up the complaint counts by month; for transit_arrests_monthly.csv, add up arrests by month. Then join on month. Add up counts, never rates or flags.
  • subway_complaints_by_offence_monthly.csv and subway_complaints_by_code_monthly.csv join the monthly table on month, many rows to one.
  • fare_evasion_quarterly.csv joins subway_ridership_monthly.csv on year and quarter, one quarter to three months.
  • For one year, subway_station_crosswalk.csv joins subway_stations_annual.csv on complex_id, many places to one complex; across years the join multiplies rows, so never add up the crosswalk's complaints after it. subway_complaint_records.csv joins the station table on complex_id and year (leave out late_report rows to match the monthly table).
  • For transit_major_felonies_fiscal.csv, add up the monthly table's counts and rides by fiscal_year and recompute the rates; the monthly table starts halfway through fiscal 2014, so its first whole fiscal year is 2015. The fiscal file counts the whole transit system, not the subway premises.
  • events.csv joins sources.csv on source_id.
  • Keep every row of the monthly table when joining: an estimate the MTA has not published stays empty.

A few terms

A few terms used throughout. law_category is the NYPD's legal category: felony, misdemeanour or violation. The six major felonies are murder, rape, robbery, felony assault, burglary and grand larceny, leaving out grand larceny of a motor vehicle; the subway-premises records hold no murders. key_code (the NYPD's KY_CD) is the broad offence code and pd_code (PD_CD) the finer internal code within it. A station complex is the MTA's grouping of stations joined by passageways. Fiscal years run from July to June and are named for the year they end in.

Five questions to start with

  1. Compared with 2019, how have recorded felony rates changed per paid ride and per estimated entry? The MTA counts paid rides. About 4% of subway entries in early 2019 were unpaid, and about 10% in early 2025. If entries and recorded complaints stayed the same, a higher unpaid share would mean fewer paid rides and so a higher rate per paid ride. Compare the monthly table's rates per paid ride and per estimated entry, then use subway_ridership_monthly.csv to move the unpaid share one percentage point above or below the MTA's estimate: the same complaints, two denominators, and a choice about which one to report.

    Files: subway_crime_monthly.csv, subway_ridership_monthly.csv, fare_evasion_quarterly.csv

  2. Which offences fell with ridership in 2020, and which did not? In 2020 the subway carried 38% of its 2019 rides. Grand larcenies fell by half, closer to the fall in riders, but felony assaults stayed at 96% of their 2019 number and robberies at 105%. The daily and monthly files let you measure, offence by offence, how closely recorded complaints track ridership, and ask what the offences that held steady have in common.

    Files: subway_crime_annual.csv, subway_crime_monthly.csv, subway_crime_daily.csv

  3. Which station complexes have the highest major felony complaint rates per entry: the busy hubs, or quieter stations? Counts and rates rank stations differently. In 2025 the Bronx's station complexes recorded almost three times Manhattan's rate of major felony complaints per entry. The station table pairs matched complaints with MTA station entries for each complex and year. Compare the rankings by count and by rate, then recalculate them without the complaints matched less surely, using station_match in the record file.

    Files: subway_stations_annual.csv, subway_station_crosswalk.csv, subway_complaint_records.csv

  4. Are major felony complaint rates higher at weekends than on weekdays? From 2023 to 2025 the rate of major felony complaints per ride was about twice as high at weekends as on weekdays. Use the daily file to compare this gap across months and offences. The hourly file shows when complaints began, but there are no hourly ridership figures here, so it cannot show whether rates per ride differ by hour.

    Files: subway_crime_daily.csv, subway_crime_by_hour.csv

  5. Theft of services: what do complaints, arrests and the MTA's survey each measure? Complaints of theft of services, the offence that covers fare evasion, went from 54 in 2019 to 13,009 in 2025. Arrests for it in the Transit jurisdiction went from 2,712 to 12,475 over the same years, yet they were 22,776 in 2014, when complaints numbered 50. The MTA's own survey has the unpaid share rising from about 4% to 10%. Three records of one behaviour move three different ways. Set side by side month by month, they show where and when they diverge; they cannot by themselves divide that divergence between behaviour and record-keeping.

    Files: transit_arrests_monthly.csv, subway_crime_monthly.csv, fare_evasion_quarterly.csv, city_context_monthly.csv

20 more questions are listed below and set out in QUESTIONS.md.

For learning and teaching

subway_complaint_records.csv holds 187,739 complaint records: the 187,630 complaints in the monthly table (January 2014 to June 2026) and the 109 late reports, filed in 2026 about earlier years, two of them about 2005 and 2006 (late_report is true; leave them out to reproduce the monthly table). Each row has the fields the NYPD publishes: when the offence began, ended and was reported, the offence and its codes, attempted or completed, the place, and the age group and sex of the victim and of the suspect as recorded. Most columns are categorical, from a handful of values (law category, borough, day of the week) to hundreds (station, offence code): a good set for classification (predicting a category), encoding (turning labels into numbers) and clustering (grouping similar records). Identical rows are separate complaints, so do not remove them as duplicates.

Its gaps are real. Empty cells correspond to blanks or (null) in the NYPD's file and to nothing else: there is no end date for 16,297 complaints, no suspect age group for 33,830 and no suspect sex for 31,482. Values the NYPD recorded as UNKNOWN or U are kept as they are, so a missing value and a value recorded as unknown can be told apart. missing_values.csv counts the empty cells in every file and says why they are empty.

Two kinds of information are left out on purpose: the complaint number, and the race of victims and suspects. The file is for learning, not for identifying anyone or modelling race.

Before you use these numbers

These are recorded crimes, not crime. A complaint is a report the police recorded, so the counts move with policing as well as with crime: where officers are, what they look for and how they write it down. Theft of services shows how far the two can part. Its complaints rose from 54 in 2019 to 13,009 in 2025, while arrests for it in the Transit jurisdiction rose from 2,712 to 12,475; in 2014 those arrests numbered 22,776 and the complaints 50. In 2014 an arrest for theft of services rarely came with a complaint record; by 2025 the complaints outnumbered the arrests. Read the complaint count as a record of enforcement, not as a measure of fare evasion. The six major felonies are offences victims mostly report themselves, but they are not immune.

Monthly rides before March 2020 are modelled. Through December 2019 each year's official total is spread over its months by one inferred monthly pattern; January and February 2020 together are 2020's official total less the daily figures from March. paid_rides_method says which applies to each row. The yearly totals are counted; the split into months is not. The MTA's station counts, added up, give an observed comparison from February 2017 to February 2020: in every month the counted rides are within 6% of the modelled ones, in every November 3% to 4.5% above them, and over January to May 2019, the window the article compares, within 0.4%.

Seasonal patterns and breaks are partly built in. Before March 2020 every year's rides follow the same imposed monthly pattern, so seasonal variation in rates then partly reflects how the denominator was built, and the change to counted rides coincides with the pandemic. Quarterly fare-evasion estimates are reused for each month of their quarter and are not independent monthly measurements. A rate model should account for uncertainty in rides and entries, complaint counts that vary more than a simple count model assumes (overdispersion), and links between successive months; where station_sum_rides exists, test how the conclusions change with it.

Entries are an estimate on an estimate. entries_est divides paid rides by one minus the MTA's quarterly fare-evasion share. The MTA publishes margins from 2020 (0.8 to 1.6 percentage points; 0.8 to 1.0 in the quarters the article compares; confidence level not stated), none for 2018 and 2019, and no estimate at all for April to June 2020. The scenarios in subway_ridership_monthly.csv, with the unpaid share one percentage point above or below the estimate, show how much it moves a comparison; they are scenarios, not confidence bounds, and do not cover every published margin.

Definitions changed. Each year is counted under that year's law. New York expanded the legal definition of felony assault to more transit workers from 25 September 2022 and 19 July 2024, and to retail workers from 17 October 2024 (felony_assault_widenings_in_force), and redefined rape in a law signed on 30 January 2024 whose effective date the saved bill text does not settle (events.csv). A complaint carries an offence code, not the section charged, so the counts cannot say how many assaults qualified only under a newer law.

Two places, two sources. The complaint counts are for the subway premises. The fiscal series is the Mayor's Management Report's count for the whole transit system, divided by subway rides in the same months: a descriptive ratio, not the subway-premises complaint rate. The two are close (2,093 against 2,176 for the year to June 2026, with June incomplete in the first) but not the same count. Compare within a file, not across them.

The newest months are incomplete. June 2026 has reports only to 30 June 2026, and every recent month gains late reports for a while (about 5% of December 2025's felonies were filed in the new year). Complaints reported in 2026 about months before 2026 (109) are not added back; late_reports_all gives them by month (107 of them; the other two concern months before 2014). complete is false for December 2025 and June 2026, and the yearly files count such months in months_incomplete. The report-delay file shows how long each offence took to come in; its newest years have had less time for the slowest reports.

Times and places are approximate. The start time is the one the complaint records. Many are rounded to the hour, and 00:01 is more than fifteen times as common as 00:02, the mark of a default, so the first hour after midnight is inflated; all_complaints_on_the_hour shows how much rounding there is. A station is matched from the place the NYPD records, and about 8% of complaints are matched less surely (match in the station-matching table). A zero in the station table means no complaint was matched to that complex that year, not that nothing happened there, and a station closed for part of a year has fewer months of entries.

No murders in the subway premises records. The complaint files hold no murder with the subway as its place, so their "six major felonies" are in practice five. That is not evidence that no murder happened in the subway: the transit system's few murders are in the fiscal series.

Not a measure of risk to one rider. A rate per ride is an average over very different trips, stations and hours. Policing announcements in events.csv are announcements, not measured effects, and nothing here says why a rate moved: the files can show what changed alongside it, not what caused it.

Reading the files

  • Empty cells mean unavailable or not applicable, never zero. Load counts and rides as nullable integers (pandas Int64, integer columns that can hold missing values).
  • The two complaint tables by month are sparse: within a covered month (January 2014 to June 2026), an offence with no row had no complaints. Their keys are month, law_category, offence, complaint_file and month, key_code, offence, pd_code, complaint_file. The daily, hourly and station files are full grids: every day, hour or complex-year is present.
  • In the count tables, (null) in offence, station_name, victim_age_group and similar columns is the label the NYPD's file prints for a blank, kept so that its complaints are counted. In subway_complaint_records.csv the same blank is an empty cell, ready to be treated as missing. Labels keep the source's spelling (for example HARRASSMENT 2).
  • missing_values.csv lists every column with empty cells, how many and why: a figure was not published, does not apply, or is blank in the source.
  • A month, day or hour is when the offence began (CMPLNT_FR_DT and CMPLNT_FR_TM), not when it was reported; an arrest's month is the month of the arrest.
  • events.csv keeps each date at the precision the source gives (YYYY, YYYY-MM or YYYY-MM-DD): read it as text, and do not turn a year or a month into a day.
  • Rides and entries are added up from unrounded values, then rounded; rates use the unrounded values and are rounded to four decimals. Annual and fiscal totals can therefore differ by a few rides from the sum of the monthly integers shown.
  • official_annual_total repeats on every month of its year in subway_ridership_monthly.csv, and nyc_population on every month of its year in city_context_monthly.csv: take one value per year, never add them up.
  • Every finer table counts the same complaints as the monthly table: added up to the month or the year, the daily, hourly, station, victim and report-delay files equal it exactly, and the record file does too once its late reports are left out. The build refuses to write any file unless these checks pass.

Method

The complaint counts are the NYPD's records whose premises is the subway, counted by the month, day and hour the offence began. The monthly counts by offence were retrieved on 26 September 2026, those by offence code on 11 October, and the finer extracts (day, time, report date, codes, station, victim group, and every complaint's descriptive fields) on 19 October. The build checks that each extract, added up by month, equals the earlier files in every cell, so every table counts the same complaints, and that the record file is the NYPD's extract record for record. The 2026 year-to-date file ends with reports to 30 June 2026; its complaints about earlier years (late reports) are kept out of the earlier years' counts and shown in their own columns.

Monthly paid rides before March 2020 are estimates. Through December 2019, each calendar year's official total is spread over its months by an inferred 2019 monthly pattern, rebuilt from the MTA's comparisons of each 2024 day with its 2019 equivalent, with 29 February 2024 left out. January and February 2020 together are 2020's official total less the daily counts for March to December, split between the two months by the same pattern, February's weight multiplied by 29/28 for its leap day. From March 2020 a month's rides are the sum of the MTA's daily figures, which come within 0.2% of the official yearly totals for 2021 to 2024. Entries are each month's paid rides divided by one minus the MTA's unpaid share for its quarter, taken to hold evenly through the quarter. The MTA's station counts, added up by month (station_sum_rides), are a separate series from February 2017: they measure entries a little differently (about 1% above the daily totals since 2024) and are kept beside the paid rides, not mixed into them.

Stations are matched by place. The NYPD records a station name and coordinates for every subway complaint, but its names are older or shared ("125 STREET" is four stations). Each recorded place is matched to the nearest MTA station within 300 metres whose name shares an identifying word; failing that, to the station sharing most words within 800 metres (1,500 for two or more words), and failing that, to the nearest station of all. The station-matching table keeps the distance and the kind of match for every place: 92% of complaints are matched by name within 300 metres and under 1% are left uncertain. A station complex is the MTA's grouping of stations joined by passageways; its name, borough and coordinates are the MTA's current ones.

Every row of the article's own data file is reproduced from these files before they are published, every figure this card quotes is checked against them, and the build is checked to rebuild byte for byte.

Files

FileRowsSizeWhat it holds
subway_crime_monthly.csv 150 29 KB Start here. One row per month, January 2014 to June 2026, with subway complaint counts, paid rides, estimated entries and rates per million of each. Includes flags for the ridership method and the reporting window.
subway_crime_annual.csv 12 3 KB One row per whole calendar year, 2014 to 2025 (2026 is not included): the monthly table added up, with the year's official ride total beside the rides used and the flags a year inherits from its months. Reproduces the article's year-by-year chart.
subway_ridership_monthly.csv 351 29 KB Monthly paid subway rides from July 1997 (the start of fiscal 1998) to September 2026, with method flags, official yearly totals and fare-evasion estimates. Includes estimated entries and two scenarios with the unpaid share one percentage point higher or lower. Station entries, added up from February 2017, check the modelled months.
fare_evasion_quarterly.csv 34 911 B The MTA's quarterly estimate of the share of subway entries that are unpaid, from traffic checkers' counts at a sample of stations, with its published margin of error, as published on Open NY.
transit_major_felonies_fiscal.csv 29 5 KB The long view: the Mayor's Management Report's major felonies in the whole transit system for each fiscal year (July to June), 1998 to 2026, beside the subway's paid rides in the same months. A ratio across two scopes, not the subway-premises complaint rate.
subway_crime_daily.csv 4,564 387 KB One row per day, 1 January 2014 to 30 June 2026: complaints by the day the offence began, the subway's paid rides that day (from 1 March 2020) and Central Park's temperature, rain and snow. For weekday and weekend, weather and before-and-after questions.
subway_crime_by_hour.csv 7,200 279 KB Complaints by month, weekday or weekend, and the hour the offence began (0 to 23), every hour present. For when in the day crime happens and for the overnight closure of May 2020 to May 2021. Times are as recorded and often rounded.
subway_stations_annual.csv 5,551 578 KB One row per station complex and year, with the complaints matched to it, its entries and rates per million entries. Entries begin in February 2017, and a rate needs entries for every month of the year's complaints. 2026 covers January to June. Every complex is listed in every year.
subway_station_crosswalk.csv 2,849 247 KB Every place the NYPD records for a subway complaint (a station name, a borough and coordinates), with how many complaints it holds and the MTA station complex it is matched to, the distance and the kind of match. Check or redo the matching here.
subway_complaints_by_offence_monthly.csv 4,823 343 KB Complaint counts by month, law category and the NYPD's offence label, as the files print it. This table supplies the monthly table's offence and law-category totals. Sparse: within a covered month, an offence with no row had no complaints.
subway_complaints_by_code_monthly.csv 12,037 1.1 MB Complaint counts by month, the NYPD's key offence code and its internal offence code, which tell kinds of the same offence apart: assaults on police from other assaults, pickpocketing from bag-snatching, theft of services from other theft. Sparse, like the offence table.
subway_victims_annual.csv 3,668 174 KB Complaints by year, law category, offence, and the victim's age group and sex as the NYPD records them. Many complaints have no person as victim: offences against the State, such as fare evasion, and against businesses. 2026 covers January to June.
subway_report_delay_annual.csv 728 34 KB Complaints by year, offence group and the delay between the day the offence began and the day it was reported, every band present. It describes delays among the complaints already in the files: the late reports are not included, the newest years have had less time for the slowest reports, and reports still to come cannot be seen.
transit_arrests_monthly.csv 9,204 646 KB Arrests the NYPD records in its Transit jurisdiction (jurisdiction code 1, the subway), by month of arrest, law category and the offence charged, with its codes. An arrest is not linked to a complaint, and counts when it is made.
city_context_monthly.csv 150 14 KB One row per month: recorded crime across the whole city, the subway included, counted the way the subway's is; the subway's share of it; the city's population; complaints and rides on buses; Transit arrests; and the shelter census. Joins the monthly table one to one on month.
events.csv 23 6 KB Dated events that bear on reading the series: changes to the legal definitions of felony assault and rape, the policing announcements for the subway, the lockdown, the overnight closure, fare increases, congestion pricing, and the points where a source starts or stops. Each names its source. Announcements are what was announced, not measured effects.
subway_complaint_records.csv.gz 187,739 6.3 MB 187,739 complaint records: the 187,630 complaints in the monthly table and 109 late reports (late_report). Each has the fields the NYPD publishes: when the offence began, ended and was reported, the offence and its codes, the place, and the victim's and suspect's age group and sex. Empty cells correspond to blanks or (null) in the NYPD's file; recorded unknown values are kept. Identical rows are separate complaints. No complaint number and no race. Compressed here (gzip); pandas.read_csv reads it as it is.
missing_values.csv 53 7 KB For every column of every CSV here that has empty cells: how many, what share, and why they are empty (not published, not applicable, or blank in the source).
QUESTIONS.md 13 KB Research questions, each with why it is worth asking, what the files can and cannot show, and the files it needs; the first five are on the card.
data_dictionary.csv 283 41 KB Column names, types, definitions, value classes and licence layers for every CSV in this dataset.
sources.csv 50 32 KB Every source the files are built from: publisher, title, links, when it was retrieved (in Coordinated Universal Time, UTC), the SHA-256 checksum and name of the saved copy (to verify the file), where in it the figures are, and its terms.
LICENSE.md 3 KB The three licence layers: government records under their publishers' terms, SparkyData's additions under CC BY 4.0, the code under MIT.
build_dataset.py 52 KB The builder (MIT): the tables and the checks run before anything is published. It imports SparkyData's library and the article's own functions, which are in the article's code bundle; it is for reading, not a standalone rebuild.
analysis.py 61 KB The script behind the article (MIT): it computes every figure in the article, not these files. It runs inside the article's code bundle, linked from the article.
README.md 88 KB Everything on this page in one file, to keep beside the data.

Columns

Each column is classed by where its values come from: observed (counted from administrative records or printed by the agency), published estimate (an estimate the agency publishes), modelled (our estimate, on a stated assumption) or derived (arithmetic on the others). The same list is in data_dictionary.csv.

subway_crime_monthly.csv: Subway crime and rides by month, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedMonth in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM; not the month it was reported.
yearintegerobservedCalendar year.
fiscal_yearintegerderivedNew York City fiscal year (July to June), named for the year it ends in.
six_majorintegerobservedComplaints of the six major felonies (murder, rape, robbery, felony assault, burglary, grand larceny; not grand larceny of a motor vehicle) whose premises is the subway.
murderintegerobservedMurder and non-negligent manslaughter. Zero in every month: the files hold no murder with the subway as its place, which is not evidence that none happened (the fiscal series counts the transit system's).
rapeintegerobservedRape complaints (the definition was widened by a law signed on 30 January 2024; see events.csv).
robberyintegerobservedRobbery complaints: theft by force or threat.
felony_assaultintegerobservedFelony assault complaints (NYPD key code KY_CD 106), the serious grade of assault, widened in 2022 and 2024 (see felony_assault_widenings_in_force).
burglaryintegerobservedBurglary complaints.
grand_larcenyintegerobservedGrand larceny complaints, the felony grade of theft (not of a motor vehicle).
felony_assault_ordinaryintegerobservedFelony assaults with internal offence code PD_CD 109 (ASSAULT 2,1,UNCLASSIFIED). Not a constant-definition or worker-free category: newly covered workers can sit here.
felony_assault_strangulationintegerobservedFelony assaults with PD_CD 105 (strangulation).
felony_assault_police_or_peace_officerintegerobservedFelony assaults with PD_CD 106 (on a police or peace officer).
felony_assault_other_public_service_employeeintegerobservedFelony assaults with PD_CD 108 (on another public service employee; from 2017). Newly covered transit workers may sit here or in PD_CD 109.
theft_of_servicesintegerobservedTheft of services complaints, PD_CD 478 under key code 343 (fare evasion falls under it): a record of enforcement, not a crime trend. Counted by code because its offence label changed over the years.
all_feloniesintegerobservedEvery felony complaint whose premises is the subway, including offences the police mostly find themselves (weapons, drugs).
all_misdemeanorsintegerobservedEvery misdemeanour complaint (dominated by enforcement in recent years).
all_violationsintegerobservedEvery violation complaint.
all_complaintsintegerobservedFelonies, misdemeanours and violations.
paid_ridesintegermixedPaid subway entries (taps and swipes) in the month: the MTA's daily figures added up from March 2020; modelled before (paid_rides_method says how).
paid_rides_methodstringderivedHow paid_rides was made: annual_total_x_2019_pattern (the year's official total spread by an inferred 2019 month pattern; to December 2019), annual_total_less_daily (2020's official total less its daily figures from March, split by that pattern with February weighted 29/28; January and February 2020), daily_counts (the MTA's daily figures added up; from March 2020).
unpaid_sharenumberpublished estimateThe MTA's estimate of the share of entries that are unpaid, for the month's quarter (a fraction). Empty: Empty before 2018, when the MTA's estimates begin, and for April to June 2020, when none was published.
unpaid_share_moenumberpublished estimateThe MTA's published margin of error on unpaid_share (a fraction; confidence level not stated). Empty: Empty before 2020, when the MTA begins publishing margins, and for April to June 2020.
entries_estintegermodelledEstimated entries, paid or not: paid_rides / (1 - unpaid_share). Empty: Empty where unpaid_share is, as there is no estimate to divide by.
six_major_per_m_paidnumberderivedSix major felony complaints per million paid rides.
felony_assault_per_m_paidnumberderivedFelony assault complaints per million paid rides.
robbery_per_m_paidnumberderivedRobbery complaints per million paid rides.
grand_larceny_per_m_paidnumberderivedGrand larceny complaints per million paid rides.
six_major_per_m_entriesnumberderivedSix major felony complaints per million estimated entries, paid or not. Empty: Empty where entries_est is.
felony_assault_per_m_entriesnumberderivedFelony assault complaints per million estimated entries. Empty: Empty where entries_est is.
robbery_per_m_entriesnumberderivedRobbery complaints per million estimated entries. Empty: Empty where entries_est is.
grand_larceny_per_m_entriesnumberderivedGrand larceny complaints per million estimated entries. Empty: Empty where entries_est is.
felony_assault_widenings_in_forceintegerderivedHow many of the expansions of felony assault since 2019 were in force for any part of the month: 1 from September 2022, 2 from July 2024, 3 from October 2024 (events.csv). A count of legal changes, not a measure of their size; a transition month holds both regimes.
complaint_filestringderivedThe NYPD file the month's counts come from: historic (to December 2025) or year_to_date (2026).
report_cutoffstringobservedThe last report date in that file (YYYY-MM-DD): complaints reported after it are not in the count.
late_reports_allintegerobservedComplaints about this month (before 2026) found in the 2026 year-to-date file and left out of the historic counts (107 from 2014 on; the article's 109 include two about earlier months). Empty: Empty for 2026's months, whose late reports are already in their counts: not applicable, not zero.
late_reports_six_majorintegerobservedThe six major felonies among late_reports_all. Empty: Empty for 2026's months: not applicable, not zero.
completebooleanderivedA reporting-window flag, not a guarantee of final counts: true when the file's report cutoff is at least the end of the following calendar month. False for December 2025 and June 2026.
subway_crime_annual.csv: Subway crime and rides by calendar year, 2014–2025
ColumnTypeClassWhat it is
yearintegerobservedCalendar year.
six_majorintegerobservedComplaints of the six major felonies on the subway premises in the year (grand larceny of a motor vehicle excluded).
murderintegerobservedMurder complaints on the subway premises in the year: zero, which is not evidence that none happened (the fiscal series counts the transit system's).
rapeintegerobservedRape complaints in the year (the definition was widened by a law signed on 30 January 2024).
robberyintegerobservedRobbery complaints in the year.
felony_assaultintegerobservedFelony assault complaints (KY_CD 106) in the year.
burglaryintegerobservedBurglary complaints in the year.
grand_larcenyintegerobservedGrand larceny complaints in the year (not of a motor vehicle).
felony_assault_ordinaryintegerobservedFelony assaults with PD_CD 109 in the year. Not a constant-definition category: newly covered workers can sit here.
felony_assault_strangulationintegerobservedFelony assaults with PD_CD 105 (strangulation) in the year.
felony_assault_police_or_peace_officerintegerobservedFelony assaults with PD_CD 106 (on a police or peace officer) in the year.
felony_assault_other_public_service_employeeintegerobservedFelony assaults with PD_CD 108 (on another public service employee) in the year.
theft_of_servicesintegerobservedTheft of services complaints (PD_CD 478 under key code 343) in the year: a record of enforcement, not a crime trend.
all_feloniesintegerobservedFelony complaints in the year.
all_misdemeanorsintegerobservedMisdemeanour complaints in the year.
all_violationsintegerobservedViolation complaints in the year.
all_complaintsintegerobservedEvery complaint in the year.
paid_ridesintegerobservedThe year's paid rides: the official total to 2020, the MTA's daily figures added up from 2021 (within 0.2% of the official totals in 2021-2024).
paid_rides_methodstringderivedofficial_total (to 2020) or daily_counts (from 2021).
official_annual_totalintegerobservedThe MTA's official yearly subway ridership. Empty: Empty for 2025: the MTA's latest yearly page is for 2024.
unpaid_sharenumbermodelled1 - paid_rides / entries_est for the year: the unpaid share implied by its quarters. Empty: Empty before 2018 (no estimate) and for 2020 (none for April to June).
entries_estintegermodelledThe year's estimated entries, added up from unrounded monthly values. Empty: Empty where any month of the year has no estimate (before 2018, and 2020).
six_major_per_m_paidnumberderivedSix major felony complaints per million paid rides in the year.
felony_assault_per_m_paidnumberderivedFelony assault complaints per million paid rides in the year.
robbery_per_m_paidnumberderivedRobbery complaints per million paid rides in the year.
grand_larceny_per_m_paidnumberderivedGrand larceny complaints per million paid rides in the year.
six_major_per_m_entriesnumberderivedSix major felony complaints per million estimated entries in the year. Empty: Empty where entries_est is.
felony_assault_per_m_entriesnumberderivedFelony assault complaints per million estimated entries in the year. Empty: Empty where entries_est is.
robbery_per_m_entriesnumberderivedRobbery complaints per million estimated entries in the year. Empty: Empty where entries_est is.
grand_larceny_per_m_entriesnumberderivedGrand larceny complaints per million estimated entries in the year. Empty: Empty where entries_est is.
felony_assault_widenings_in_forceintegerderivedThe most expansions of felony assault in force in any month of the year (0 to 3). A year with a change holds more than one regime.
months_incompleteintegerderivedHow many of the year's months are flagged as not yet complete (2025: one, December).
subway_ridership_monthly.csv: Subway rides by month, 1997–2026
ColumnTypeClassWhat it is
monthstringobservedMonth (YYYY-MM).
yearintegerobservedCalendar year.
quarterintegerobservedCalendar quarter (1-4), the period of the fare-evasion estimate.
fiscal_yearintegerderivedNew York City fiscal year (July to June).
paid_ridesintegermixedPaid subway entries in the month: the MTA's daily figures added up from March 2020, modelled before (paid_rides_method).
paid_rides_methodstringderivedannual_total_x_2019_pattern (to December 2019), annual_total_less_daily (January and February 2020) or daily_counts (from March 2020).
official_annual_totalintegerobservedThe year's official subway ridership (NYU Rudin's table of New York City Transit's counts to 2013, the MTA's yearly pages from 2014). Repeated on every month of its year: take one value per year, never add it up. Empty: Empty for 2025 and 2026: no official yearly figure has been published yet.
unpaid_sharenumberpublished estimateThe MTA's unpaid share for the month's quarter (a fraction). Empty: Empty before 2018, when the MTA's estimates begin, for April to June 2020, when none was published, and for July to September 2026, not yet published.
unpaid_share_moenumberpublished estimateIts published margin of error (a fraction). Empty: Empty before 2020, when the MTA begins publishing margins, and wherever unpaid_share is empty.
entries_estintegermodelledEstimated entries, paid or not: paid_rides / (1 - unpaid_share). Empty: Empty where unpaid_share is.
entries_est_unpaid_minus_1ptintegermodelledEntries with the unpaid share one percentage point (0.01) lower: a scenario, not a confidence bound, and not guaranteed to cover every published margin. Empty: Empty where unpaid_share is.
entries_est_unpaid_plus_1ptintegermodelledEntries with the unpaid share one percentage point (0.01) higher: a scenario, not a confidence bound. Empty: Empty where unpaid_share is.
station_sum_ridesintegerobservedThe MTA's entries at every station complex in the month, added up (MTA Subway Station Monthly Ridership). Counted, not modelled, but not the same measure as paid_rides: about 1% above the daily totals since 2024. Use it to check the modelled months or as another monthly denominator; never mix it into paid_rides. Empty: Empty before February 2017, when the MTA's station file starts, and for September 2026, after its latest month.
fare_evasion_quarterly.csv: Subway fare evasion by quarter, 2018–2026
ColumnTypeClassWhat it is
periodstringobservedQuarter (YYYY-Qn).
yearintegerobservedCalendar year.
quarterintegerobservedCalendar quarter (1-4).
unpaid_sharenumberpublished estimateEstimated share of entries that are unpaid (a fraction). Empty: Empty for 2020 Q2: no estimate was published.
margin_of_errornumberpublished estimatePublished margin of error (a fraction; confidence level not stated). Empty: Empty before 2020 Q1, when the MTA begins publishing margins, and for 2020 Q2.
transit_major_felonies_fiscal.csv: Transit-system major felonies by fiscal year, 1998–2026
ColumnTypeClassWhat it is
fiscal_yearintegerobservedNew York City fiscal year (July to June), named for the year it ends in.
monthsstringderivedThe months the fiscal year covers (YYYY-MM to YYYY-MM).
major_feloniesintegerobservedMajor felony crime in the transit system as the Mayor's Management Report prints it: murder, rape, robbery, felony assault, burglary and grand larceny, under each year's law.
crime_scopestringderivedWhat major_felonies counts: the whole transit system under the NYPD's Transit Bureau.
rides_scopestringderivedWhat paid_rides counts: subway paid entries.
mmr_source_idstringderivedThe source the figure was read from (sources.csv). Where editions overlap they agree to the felony; the latest is kept.
notestringobservedA remark the source makes about the year (fiscal 1998: based on preliminary data). Empty: Empty where the source makes no remark about the year.
paid_ridesintegermixedPaid subway rides in the fiscal year's twelve months, added up from the unrounded monthly values: modelled months to February 2020, the MTA's daily figures after (paid_rides_method).
paid_rides_methodstringderivedHow the year's months were built (see subway_ridership_monthly.csv); fiscal 2020 mixes all three.
major_felonies_per_m_paidnumberderivedTransit-system major felonies per million paid subway rides: a ratio across two scopes.
unpaid_sharenumbermodelledThe fiscal year's implied unpaid share (1 - paid / entries). Empty: Empty before fiscal 2019 (no estimate for every month) and for fiscal 2020 (none for April to June 2020).
entries_estintegermodelledEstimated subway entries, paid or not, in the fiscal year. Empty: Empty where unpaid_share is.
major_felonies_per_m_entriesnumberderivedTransit-system major felonies per million estimated subway entries. Empty: Empty where entries_est is.
subway_crime_daily.csv: Subway crime, rides and weather by day, 2014–2026
ColumnTypeClassWhat it is
datestringobservedThe day the recorded offence began (CMPLNT_FR_DT), YYYY-MM-DD.
yearintegerobservedCalendar year.
monthstringobservedYYYY-MM, the key to the monthly files.
day_of_weekstringderivedMonday to Sunday.
weekendbooleanderivedTrue on Saturday and Sunday. Public holidays are not flagged.
six_majorintegerobservedComplaints of the six major felonies that began that day.
felony_assaultintegerobservedFelony assault complaints that began that day.
robberyintegerobservedRobbery complaints that began that day.
grand_larcenyintegerobservedGrand larceny complaints that began that day.
all_feloniesintegerobservedFelony complaints that began that day.
all_misdemeanorsintegerobservedMisdemeanour complaints that began that day.
all_violationsintegerobservedViolation complaints that began that day.
all_complaintsintegerobservedEvery subway complaint that began that day.
theft_of_servicesintegerobservedTheft of services complaints (PD_CD 478 under key code 343): a record of enforcement.
paid_ridesintegerobservedThe MTA's subway ridership figure for the day, which it labels 'Total Estimated Ridership' and builds from its fare-system counts. Empty: Empty before 1 March 2020, when the MTA's daily figures begin.
tmax_fintegerobservedCentral Park's maximum temperature, whole degrees Fahrenheit (NOAA's Global Historical Climatology Network - Daily).
tmin_fintegerobservedCentral Park's minimum temperature, whole degrees Fahrenheit.
precip_innumberobservedCentral Park's precipitation (rain and melted snow), inches.
snow_innumberobservedCentral Park's snowfall, inches.
felony_assault_widenings_in_forceintegerderivedHow many expansions of felony assault were in force that day (0 to 3; events.csv).
completebooleanderivedThe day's month's reporting-window flag: true when the file's report cutoff reaches at least the end of the following calendar month. Not a guarantee of final counts.
subway_crime_by_hour.csv: Subway crime by hour of the day, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedYYYY-MM of the day the offence began.
day_typestringderivedweekday (Monday to Friday) or weekend (Saturday and Sunday).
hourintegerobservedThe hour of the recorded start time (CMPLNT_FR_TM), 0 to 23: 0 is midnight to 00:59. 00:01 is a common default, so hour 0 is inflated.
six_majorintegerobservedComplaints of the six major felonies that began in the hour.
felony_assaultintegerobservedFelony assault complaints that began in the hour.
robberyintegerobservedRobbery complaints that began in the hour.
grand_larcenyintegerobservedGrand larceny complaints that began in the hour.
all_feloniesintegerobservedFelony complaints that began in the hour.
all_complaintsintegerobservedEvery subway complaint that began in the hour.
all_complaints_on_the_hourintegerobservedComplaints whose recorded start time is exactly on the hour (HH:00:00): a measure of rounding in the times.
completebooleanderivedThe month's reporting-window flag: true when the file's report cutoff reaches at least the end of the following calendar month.
subway_stations_annual.csv: Subway crime and entries by station complex and year, 2014–2026
ColumnTypeClassWhat it is
complex_idintegerobservedThe MTA's station complex id (Complex ID in its station list, station_complex_id in its ridership).
station_complexstringobservedThe complex's current name, with the routes that stop there, as the MTA's ridership names it.
boroughstringobservedThe complex's borough, as the MTA gives it.
latitudenumberobservedThe complex's latitude (MTA, current).
longitudenumberobservedThe complex's longitude (MTA, current).
yearintegerobservedCalendar year of the complaints.
monthsintegerderivedMonths of complaints the year covers: 12, or 6 for 2026 (January to June).
months_incompleteintegerderivedHow many of the year's months are flagged as not yet complete in the monthly table (2025: December; 2026: June).
six_majorintegerobservedComplaints of the six major felonies at places matched to the complex. A zero means no complaint was matched there that year, not that nothing happened.
felony_assaultintegerobservedFelony assault complaints matched to the complex.
robberyintegerobservedRobbery complaints matched to the complex.
grand_larcenyintegerobservedGrand larceny complaints matched to the complex.
all_feloniesintegerobservedFelony complaints matched to the complex.
all_complaintsintegerobservedEvery complaint matched to the complex.
all_complaints_matched_by_nameintegerderivedOf all_complaints, those whose place was matched by name within 300 metres (match 'name' in the station-matching table); the rest were matched less surely.
ridesintegerobservedThe MTA's entries at the complex over the same months (MTA Subway Station Monthly Ridership). Empty: Empty before 2017, when the MTA's station file starts, and in years the station file has no month for the complex (three Staten Island Railway stations).
ride_monthsintegerderivedMonths of entries in rides: 11 in 2017 (the file starts in February), fewer where a station has months missing, 0 before 2017.
six_major_per_m_ridesnumberderivedSix major felony complaints per million entries at the complex. Empty: Empty where the entries do not cover every month of the year's complaints: every year before 2018, and years in which the station file lacks some months for the complex.
felony_assault_per_m_ridesnumberderivedFelony assault complaints per million entries at the complex. Empty: Empty where the entries do not cover every month of the year's complaints.
robbery_per_m_ridesnumberderivedRobbery complaints per million entries at the complex. Empty: Empty where the entries do not cover every month of the year's complaints.
all_complaints_per_m_ridesnumberderivedEvery complaint per million entries at the complex. Empty: Empty where the entries do not cover every month of the year's complaints.
subway_station_crosswalk.csv: Station matching: the NYPD's station names to the MTA's station complexes
ColumnTypeClassWhat it is
station_namestringobservedThe station name the NYPD records (STATION_NAME), as printed; '(null)' where blank.
boroughstringobservedThe borough the NYPD records (BORO_NM).
latitudenumberobservedThe latitude the NYPD records.
longitudenumberobservedThe longitude the NYPD records.
complaintsintegerobservedComplaints at this place across the whole record file: the monthly table's complaints plus the 109 late reports (two of them about 2005 and 2006).
complex_idintegerderivedThe MTA station complex the place is matched to.
matched_stationstringobservedThe MTA station (stop name) the match was made to.
distance_mnumberderivedMetres from the recorded place to that station.
matchstringderivedname: a station sharing an identifying word within 300 m; name_far: the station sharing the most words, further away (up to 800 m, or 1,500 m for two or more words); distance: no name in common, the nearest within 300 m (often an older name, such as PACIFIC STREET for Atlantic Av-Barclays Ctr); uncertain: no name in common and further than 300 m.
subway_complaints_by_offence_monthly.csv: Every subway complaint offence by month, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedMonth in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM.
law_categorystringobservedFELONY, MISDEMEANOR or VIOLATION (LAW_CAT_CD).
offencestringobservedThe NYPD's offence description (OFNS_DESC) as the files print it, spelling included; '(null)' is the source's own label for complaints with no description. Labels can change over the years while the offence does not.
is_major_sixbooleanderivedOne of the six major felonies (grand larceny of a motor vehicle excluded).
complaintsintegerobservedNumber of complaints in this month, law category and offence.
complaint_filestringderivedhistoric or year_to_date: the NYPD file the counts come from.
report_cutoffstringobservedThe last report date in that file (YYYY-MM-DD).
completebooleanderivedThe month's reporting-window flag: true when the file's report cutoff reaches at least the end of the following calendar month. Not a guarantee of final counts.
subway_complaints_by_code_monthly.csv: Every subway complaint by internal offence code, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedMonth in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM.
key_codeintegerobservedThe NYPD's key offence code (KY_CD), e.g. 105 robbery, 106 felony assault, 109 grand larceny, 343 other offences related to theft.
offencestringobservedThe offence description (OFNS_DESC) as printed; a label can change over the years while the codes do not.
pd_codeintegerobservedThe NYPD's internal offence code (PD_CD), e.g. 109 ordinary felony assault, 478 theft of services, 475 unauthorised sale of transit service.
pd_descriptionstringobservedThe internal code's description (PD_DESC) as printed.
complaintsintegerobservedNumber of complaints in this month and offence-code group.
complaint_filestringderivedhistoric or year_to_date: the NYPD file the counts come from.
report_cutoffstringobservedThe last report date in that file (YYYY-MM-DD).
completebooleanderivedThe month's reporting-window flag: true when the file's report cutoff reaches at least the end of the following calendar month. Not a guarantee of final counts.
subway_victims_annual.csv: Subway complaints by victim age group and sex, 2014–2026
ColumnTypeClassWhat it is
yearintegerobservedCalendar year the offence began.
law_categorystringobservedFELONY, MISDEMEANOR or VIOLATION.
offencestringobservedThe offence description (OFNS_DESC) as printed.
victim_age_groupstringobservedVIC_AGE_GROUP as printed: <18, 18-24, 25-44, 45-64, 65+, UNKNOWN, '(null)' (blank in the source), and a few values that are not ages (such as -59 or 951), kept as the source has them.
victim_sexstringobservedVIC_SEX as printed: F female, M male, D a business or organisation, E the People of the State of New York (offences against the public), L not defined in the NYPD's notes.
complaintsintegerobservedNumber of complaints in this year, law category, offence and victim group.
months_incompleteintegerderivedHow many of the year's months are flagged as not yet complete in the monthly table.
subway_report_delay_annual.csv: How long subway crimes took to be reported, 2014–2026
ColumnTypeClassWhat it is
yearintegerobservedCalendar year the offence began.
offence_groupstringderivedrape, robbery, felony_assault, burglary, grand_larceny (the five major felonies the records hold), or other_felonies, misdemeanors, violations.
lag_bandstringderivedsame day, 1 day, 2-7 days, 8-30 days, 31-90 days, 91-365 days, over a year.
lag_days_minintegerderivedThe band's shortest delay in days.
lag_days_maxintegerderivedThe band's longest delay in days. Empty: Empty for 'over a year', which has no upper limit.
complaintsintegerobservedComplaints reported with that delay (RPT_DT minus CMPLNT_FR_DT), among those in the monthly table.
report_cutoffstringobservedThe last report date the year's file holds: a longer delay than this allows cannot appear yet.
months_incompleteintegerderivedHow many of the year's months are flagged as not yet complete in the monthly table.
transit_arrests_monthly.csv: Arrests in the Transit jurisdiction by month and charge, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedMonth of the arrest (ARREST_DATE), YYYY-MM.
law_categorystringobservedLAW_CAT_CD as printed: F felony, M misdemeanour, V violation, I infraction, and a few other codes the file holds. Empty: Empty where the NYPD's arrest file is blank.
key_codeintegerobservedKey offence code (KY_CD) of the charge. Empty: Empty where the NYPD's arrest file is blank.
offencestringobservedOffence description (OFNS_DESC) as printed. Empty: Empty where the NYPD's arrest file is blank.
pd_codeintegerobservedInternal offence code (PD_CD); 478 under key code 343 is theft of services. Empty: Empty where the NYPD's arrest file is blank.
pd_descriptionstringobservedInternal code description (PD_DESC) as printed. Empty: Empty where the NYPD's arrest file is blank.
arrestsintegerobservedNumber of arrests in this month, law category and charge.
city_context_monthly.csv: The city around the subway by month, 2014–2026
ColumnTypeClassWhat it is
monthstringobservedYYYY-MM (the month an offence began for complaints, the month of arrest for arrests).
city_six_majorintegerobservedComplaints of the six major felonies anywhere in the city, the subway included (grand larceny of a motor vehicle excluded, as for the subway).
city_felony_assaultintegerobservedFelony assault complaints anywhere in the city.
city_robberyintegerobservedRobbery complaints anywhere in the city.
city_grand_larcenyintegerobservedGrand larceny complaints anywhere in the city (not of a motor vehicle).
city_all_complaintsintegerobservedEvery complaint anywhere in the city.
subway_share_of_city_six_majornumberderivedThe monthly table's six_major divided by city_six_major.
nyc_populationintegerpublished estimateThe five boroughs' population on 1 July of the month's year (Census Bureau estimates). Repeated on every month of its year. Empty: Empty for 2026: the Census Bureau's estimate for 1 July 2026 comes out in 2027.
bus_six_majorintegerobservedSix major felony complaints whose premises is a New York City Transit bus.
bus_felony_assaultintegerobservedFelony assault complaints on New York City Transit buses.
bus_all_complaintsintegerobservedEvery complaint on New York City Transit buses.
bus_stop_and_terminal_complaintsintegerobservedEvery complaint at bus stops and bus terminals.
bus_ridesintegerobservedThe MTA's bus ridership figures for the month, the daily figures added up; they may cover more buses than the NYPD's 'BUS (NYC TRANSIT)' premises. Empty: Empty before March 2020 (no daily bus figures) and for April to August 2020, when buses were fare-free with rear-door boarding and there is no usable count.
transit_arrestsintegerobservedTransit-jurisdiction arrests in the month (transit_arrests_monthly.csv added up).
transit_arrests_felonyintegerobservedTransit-jurisdiction arrests on a felony charge in the month.
transit_arrests_theft_of_servicesintegerobservedTransit-jurisdiction arrests for theft of services (PD_CD 478 under key code 343) in the month.
shelter_individualsintegerobservedPeople in the Department of Homeless Services' shelters, the average of the month's nightly census (Total Individuals in Shelter). Not other shelter systems, and not people sleeping outside.
shelter_census_daysintegerderivedDays in the month with a census (some days are missing in 2013-2021).
completebooleanderivedThe month's reporting-window flag for the subway complaints: true when the file's report cutoff reaches at least the end of the following calendar month. The city and bus counts come from the same files and share it.
events.csv: Law changes, policing announcements and service changes, 1995–2026
ColumnTypeClassWhat it is
datestringobservedThe event's date at the precision the source gives: YYYY, YYYY-MM or YYYY-MM-DD. Read it as text.
date_basisstringderivedWhat the date is: signed, in_force (from the act's effective-date clause, or stated by the source), announced, published, or data (a series starts, stops or has a gap).
kindstringderivedlaw, policing_announcement, service (a change to service or fares) or data.
eventstringobservedWhat happened.
bearingstringderivedWhat it means for reading the series.
source_idstringobservedThe source's id in sources.csv.
subway_complaint_records.csv.gz: Every subway complaint, one row each, 2014–2026
ColumnTypeClassWhat it is
complaint_datestringobservedThe day the offence began (CMPLNT_FR_DT), YYYY-MM-DD.
complaint_timestringobservedThe time it began (CMPLNT_FR_TM), HH:MM:SS, as recorded: often rounded to the hour, and 00:01 is a common default.
end_datestringobservedThe day it ended, where the complaint records an end (CMPLNT_TO_DT), YYYY-MM-DD. Empty: Empty where the NYPD's file is blank: no end recorded.
end_timestringobservedThe time it ended (CMPLNT_TO_TM), HH:MM:SS. Empty: Empty where the NYPD's file prints (null): no end time recorded.
report_datestringobservedThe day it was reported (RPT_DT), YYYY-MM-DD.
yearintegerderivedCalendar year of complaint_date.
monthstringderivedYYYY-MM of complaint_date, the key to the monthly files.
day_of_weekstringderivedMonday to Sunday, of complaint_date.
hourintegerderivedThe hour of complaint_time, 0 to 23.
report_delay_daysintegerderivedDays from complaint_date to report_date.
law_categorystringobservedFELONY, MISDEMEANOR or VIOLATION (LAW_CAT_CD).
offencestringobservedThe offence description (OFNS_DESC) as printed, spelling included. Empty: Empty where the NYPD's file prints (null): no description, though the codes are there.
key_codeintegerobservedThe key offence code (KY_CD).
pd_codeintegerobservedThe internal offence code (PD_CD).
pd_descriptionstringobservedThe internal code's description (PD_DESC) as printed.
is_major_sixbooleanderivedOne of the six major felonies (grand larceny of a motor vehicle excluded), as in the monthly table.
attempted_or_completedstringobservedATTEMPTED or COMPLETED (CRM_ATPT_CPTD_CD).
jurisdictionstringobservedThe jurisdiction responsible (JURIS_DESC): N.Y. TRANSIT POLICE for almost every subway complaint.
precinctintegerobservedThe precinct of the place (ADDR_PCT_CD).
boroughstringobservedThe borough (BORO_NM). Empty: Empty where the NYPD's file prints (null).
patrol_boroughstringobservedThe NYPD patrol borough (PATROL_BORO).
transit_districtintegerobservedThe NYPD transit district (TRANSIT_DISTRICT). Empty: Empty where the NYPD's file is blank.
station_namestringobservedThe station name the NYPD records (STATION_NAME), as printed. Empty: Empty where the NYPD's file prints (null).
latitudenumberobservedThe latitude the NYPD records.
longitudenumberobservedThe longitude the NYPD records.
complex_idintegerderivedThe MTA station complex the place is matched to (subway_station_crosswalk.csv).
station_matchstringderivedHow surely the place was matched: name, name_far, distance or uncertain, as in the station-matching table.
victim_age_groupstringobservedThe victim's age group as recorded (VIC_AGE_GROUP): <18, 18-24, 25-44, 45-64, 65+, UNKNOWN, and a few values that are not ages (such as -59 or 951), kept as the NYPD has them. Empty: Empty where the NYPD's file prints (null); not the same as UNKNOWN, which the NYPD recorded.
victim_sexstringobservedThe victim's sex as recorded (VIC_SEX): F female, M male, D a business or organisation, E the People of the State of New York (offences against the public), L not defined in the NYPD's notes.
suspect_age_groupstringobservedThe suspect's age group as recorded (SUSP_AGE_GROUP): <18, 18-24, 25-44, 45-64, 65+, UNKNOWN, and a few values that are not ages (such as 2024), kept as the NYPD has them. Empty: Empty where the NYPD's file prints (null); not the same as UNKNOWN, which the NYPD recorded.
suspect_sexstringobservedThe suspect's sex as recorded (SUSP_SEX): F female, M male, U unknown. Empty: Empty where the NYPD's file prints (null); U is a recorded value, not an empty cell.
complaint_filestringderivedhistoric or year_to_date: the NYPD file the complaint is in.
report_cutoffstringobservedThe last report date in that file (YYYY-MM-DD): complaints reported after it are not here.
late_reportbooleanderivedTrue for the 109 complaints reported in 2026 about earlier years (two of them about 2005 and 2006), which the monthly table leaves out of those years. Leave them out to reproduce the monthly table.
missing_values.csv: Every empty cell, counted and explained
ColumnTypeClassWhat it is
filestringderivedCSV file name.
columnstringderivedColumn name.
rowsintegerderivedRows in the file.
emptyintegerderivedEmpty cells in the column.
share_emptynumberderivedempty / rows.
why_emptystringderivedWhy the cells are empty.
data_dictionary.csv: Data dictionary
ColumnTypeClassWhat it is
filestringderivedThe file the column is in.
columnstringderivedThe column's name.
typestringderivedstring, integer, number or boolean.
classstringderivedHow the values were obtained or calculated: observed, published_estimate, modelled, derived, or mixed (varies by row; the row's method column says which). Separate from layer: derived here means a calculation.
layerstringderivedThe licence layer that applies: government (the publisher's terms), derived (SparkyData's, CC BY 4.0) or mixed (by row).
descriptionstringderivedWhat the column holds, and why it can be empty.
sources.csv: Sources and provenance
ColumnTypeClassWhat it is
source_idstringderivedThe source's id, as events.csv and transit_major_felonies_fiscal.csv cite it.
publisherstringobservedWho publishes it.
titlestringobservedIts title.
landing_pagestringobservedThe page that describes it.
urlstringobservedThe address it was fetched from (for open-data tables, the query that counted the records).
retrieved_utcstringobservedWhen it was fetched, in Coordinated Universal Time (a date can differ by one from a local date).
sha256stringobservedThe SHA-256 checksum of the saved copy, to verify the file.
saved_asstringderivedThe saved copy's path in SparkyData's repository (data/raw is a cache; data/reference is kept).
locatorstringderivedWhere in the source the figures used are (an indicator, a chart, a clause). Empty: Empty where no locator is needed: the figures come from the whole table, or the whole document.
termsstringobservedThe terms the source is published under, as recorded at retrieval.

More questions

Each is set out in QUESTIONS.md with why it is worth asking.

  1. How have transit-system felonies per paid subway ride changed since the 1990s? (transit_major_felonies_fiscal.csv, subway_ridership_monthly.csv)
  2. How has the subway's share of the city's recorded major felonies changed? (city_context_monthly.csv, subway_crime_monthly.csv)
  3. Did borough differences in major felony complaint rates widen or narrow after 2020? (subway_stations_annual.csv, subway_station_crosswalk.csv)
  4. Are recorded assault rates per ride higher on hot days? (subway_crime_daily.csv)
  5. How do rain and snow relate to ridership and recorded complaints per ride? (subway_crime_daily.csv)
  6. How has the recorded victim profile changed by age group and sex? (subway_victims_annual.csv)
  7. How did complaint counts by offence code change around changes in the law? (subway_crime_monthly.csv, subway_complaints_by_code_monthly.csv, events.csv)
  8. Is pickpocketing disappearing from the records? (subway_complaints_by_code_monthly.csv)
  9. How has the ratio of Transit arrests to recorded complaints changed? (transit_arrests_monthly.csv, subway_crime_monthly.csv)
  10. What changed in recorded complaints and arrests around the policing announcements of 2022, 2024 and 2025? (events.csv, subway_crime_monthly.csv, subway_crime_daily.csv, transit_arrests_monthly.csv)
  11. How do the shelter census and subway complaints move together? (city_context_monthly.csv, subway_crime_monthly.csv)
  12. How did ridership and complaint rates change around the start of congestion pricing? (subway_ridership_monthly.csv, subway_crime_daily.csv, subway_crime_monthly.csv, events.csv)
  13. Did the unpaid share move the same way around each fare increase? (fare_evasion_quarterly.csv, events.csv)
  14. How do reporting delays vary by offence and year? (subway_report_delay_annual.csv, subway_crime_monthly.csv)
  15. How much of the seasonal pattern before 2020 comes from the model? (subway_ridership_monthly.csv, subway_crime_monthly.csv)
  16. How do recorded complaints per ride compare on buses and on the subway? (city_context_monthly.csv, subway_crime_monthly.csv)
  17. What happened to recorded overnight complaints when the subway closed at night? (subway_crime_by_hour.csv, subway_complaint_records.csv, events.csv)
  18. Can you tell a felony from a misdemeanour by when and where it happened? (subway_complaint_records.csv)
  19. When are suspect descriptions blank, and when recorded as unknown? (subway_complaint_records.csv, missing_values.csv)
  20. How wide are the recorded windows in which offences took place? (subway_complaint_records.csv, missing_values.csv)

Sources

The SHA-256 of each saved copy is in sources.csv.

Licence and credit

Mixed licensing: government-source values remain under their publishers' terms; SparkyData's additions are Creative Commons Attribution 4.0 (CC BY 4.0); the code is MIT. The layer column of data_dictionary.csv gives the layer of every column.

Government records. Government records are reproduced or counted under their publishers' terms, which continue to apply; SparkyData does not relicense them. City sources (NYPD complaint records and complaint and arrest counts, the Department of Homeless Services' shelter census, both on NYC Open Data, and the Mayor's Management Report): the City of New York's terms, https://www.nyc.gov/main/terms-of-use. MTA sources on Open NY (ridership, station and fare-evasion figures): Open NY's terms, https://data.ny.gov/dataset/OPEN-NY-Terms-Of-Use/77gx-ii52. Central Park's daily weather comes from NOAA's National Centers for Environmental Information, and the population estimates from the US Census Bureau, under their terms. Yearly ridership for 1997 to 2013 is transcribed from the NYU Rudin Center's table of New York City Transit's counts. events.csv links to laws, press releases and news reports; none of those documents is redistributed here.

What we added. SparkyData's own additions are CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/): the monthly rides before March 2020, the estimated entries, the rates, the fiscal-year rides, the station matches, the flags, events.csv, QUESTIONS.md, missing_values.csv and the documentation.

Code. build_dataset.py and analysis.py are MIT.

Credit it as:

SparkyData (2026). NYC Subway Crime Rates and Ridership, 1998–2026 (version 2.0). SparkyData additions CC BY 4.0; government-source data under publisher terms; code MIT.
https://sparkydata.dev/data/nyc-subway-crime-and-ridership

The article gives the charts, the uncertainty of each comparison and a changelog. Corrections and questions: sparkytech.dev@gmail.com, or see corrections.

Versions

  • 1.0 (): First release.
  • 1.1 (): After an outside review: the licence marked as mixed, with LICENSE.md and the publishers' terms; a Start here section with a tested example; the by-code complaint table; flags for the ride method, the legal changes and incomplete months in the annual and long tables; source file names and locators in sources.csv. Corrected: paid rides are classed as mixed (counted from March 2020); late-report cells for 2026 are empty rather than zero; the rape row of events.csv records signing only. No count, ride or rate changed.
  • 2.0 (): A wider dataset, built around twenty-five research questions (QUESTIONS.md), with a card written as a story. Added: complaints by day (with that day's rides and weather), by hour, by station complex (with station entries and the station-matching table), by victim group and by reporting delay; every complaint as its own row, for learning and training; Transit arrests; recorded crime across the whole city, on buses, bus rides, population and the shelter census; the MTA's station counts summed by month, an observed check on the modelled months before March 2020; missing_values.csv; and the lockdown, the overnight closure, two fare increases and congestion pricing in events.csv. The code table now holds every offence code. Corrected: theft of services is code 478 under key code 343 everywhere; the card no longer says its complaints rose "while enforcement rose" without the arrests that show the recording changed. No count, ride or rate in the files of version 1.1 changed.