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

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.

```python
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:

```text
      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`.

`QUESTIONS.md` has these 5 and 20 more, with the files and limits for each; the others are listed under More questions below.

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

## What's inside

### The core: crime and rides by month

| File | Rows | What it holds |
| --- | ---: | --- |
| `subway_crime_monthly.csv` | 150 | 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 | 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 | 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 | 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 | 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. |

### By day, hour and station

| File | Rows | What it holds |
| --- | ---: | --- |
| `subway_crime_daily.csv` | 4,564 | 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 | 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 | 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 | 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. |

### What kind of crime, and to whom

| File | Rows | What it holds |
| --- | ---: | --- |
| `subway_complaints_by_offence_monthly.csv` | 4,823 | 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 | 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 | 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 | 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. |

### Enforcement and the city around it

| File | Rows | What it holds |
| --- | ---: | --- |
| `transit_arrests_monthly.csv` | 9,204 | 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 | 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 | 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. |

### Complaint by complaint, for learning and training

| File | Rows | What it holds |
| --- | ---: | --- |
| `subway_complaint_records.csv` | 187,739 | 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. |

### Reference

| File | Rows | What it holds |
| --- | ---: | --- |
| `missing_values.csv` | 53 | 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` |  | 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 | Column names, types, definitions, value classes and licence layers for every CSV in this dataset. |
| `sources.csv` | 50 | 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` |  | 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` |  | 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` |  | 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. |

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

## Observed or estimated

Every column is classed in `data_dictionary.csv` by where its values come from (`class`):

- `observed`: counted from administrative records or printed by the agency as a count of its records (complaints, fare-system entries, official totals; the MTA labels its daily and station ridership estimates, built from its fare-system counts, not a survey).
- `published_estimate`: an estimate the agency publishes, with its own sampling error (the MTA's fare-evasion share).
- `modelled`: SparkyData's estimate, built on a stated assumption (monthly rides before March 2020, entries).
- `derived`: arithmetic on the columns above (rates, sums, flags, labels).
- `mixed`: varies by row: the row's method column says which of the above applies (paid rides: observed from March 2020, modelled before).

Each column also has a licence layer (`layer`): `government` means the publisher's terms apply, `derived` means SparkyData's additions under CC BY 4.0, and `mixed` means the layer varies by row. This is separate from the class above.

## More questions

Each is set out in `QUESTIONS.md` with why it is worth asking and the files that answer it.

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

## How the numbers were made

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.

Built for the SparkyData article [Per subway ride, major felonies fell for thirty years. Felony assault broke from the fall.](https://sparkydata.dev/articles/is-the-subway-safer-per-ride) (version 1.0), which gives the charts, the uncertainty of each comparison and a changelog.

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

**SparkyData's additions.** 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 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

## Sources

With each saved copy's name, SHA-256 and retrieval time (UTC) in `sources.csv`.

- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, complaints on the subway summed by month, law category and offence](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), complaints on the subway summed by month, law category and offence](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, felony assaults and other offences related to theft on the subway, by month and offence code](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), felony assaults and other offences related to theft on the subway, by month and offence code](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic: first and last report dates and last occurrence date in the file](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date): first and last report dates and last occurrence date in the file](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, complaints on the subway summed by day, time, report date, offence, code, station, place and victim group](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), complaints on the subway summed by day, time, report date, offence, code, station, place and victim group](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, the subway's complaints with their descriptive fields (no complaint number, no race)](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), the subway's complaints with their descriptive fields (no complaint number, no race)](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, every complaint in the city summed by month, law category and offence](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), every complaint in the city summed by month, law category and offence](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Complaint Data Historic, complaints on New York City Transit buses, at bus stops and at bus terminals, by month, premises, law category and offence](https://data.cityofnewyork.us/d/qgea-i56i)
- NYPD (via NYC Open Data): [NYPD Complaint Data Current (Year To Date), complaints on New York City Transit buses, at bus stops and at bus terminals, by month, premises, law category and offence](https://data.cityofnewyork.us/d/5uac-w243)
- NYPD (via NYC Open Data): [NYPD Arrests Data (Historic), arrests in the Transit jurisdiction by month, law category and offence code](https://data.cityofnewyork.us/d/8h9b-rp9u)
- NYPD (via NYC Open Data): [NYPD Arrest Data (Year to Date), arrests in the Transit jurisdiction by month, law category and offence code](https://data.cityofnewyork.us/d/uip8-fykc)
- Metropolitan Transportation Authority (via data.ny.gov): [MTA Daily Ridership and Traffic: Beginning 2020](https://data.ny.gov/Transportation/MTA-Daily-Ridership-and-Traffic-Beginning-2020/sayj-mze2)
- Metropolitan Transportation Authority (via data.ny.gov): [MTA Daily Ridership Data: 2020 - 2025](https://data.ny.gov/Transportation/MTA-Daily-Ridership-Data-2020-2025/vxuj-8kew)
- Metropolitan Transportation Authority (via data.ny.gov): [MTA Subway Station Monthly Ridership: Beginning February 2017](https://data.ny.gov/d/ak4z-sape)
- Metropolitan Transportation Authority (via data.ny.gov): [MTA Subway Stations](https://data.ny.gov/d/39hk-dx4f)
- Metropolitan Transportation Authority (via data.ny.gov): [MTA NYCT Subway Fare Evasion: Beginning 2018](https://data.ny.gov/d/6kj3-ijvb)
- NYU Rudin Center for Transportation: [Subway Ridership 1975-2015 (NYU Rudin Center for Transportation, March 2017)](https://wagner.nyu.edu/files/faculty/publications/State%20of%20Subway%20Ridership%20-%20Mar717.pdf)
- Metropolitan Transportation Authority: [MTA: Subway and bus ridership for 2019 (annual totals 2014-2019)](https://web.archive.org/web/20200417093714id_/https://new.mta.info/agency/new-york-city-transit/subway-bus-ridership-2019)
- Metropolitan Transportation Authority: [MTA: Subway and bus ridership for 2023 (annual totals 2018-2023)](https://web.archive.org/web/20240416040137id_/https://new.mta.info/agency/new-york-city-transit/subway-bus-ridership-2023)
- Metropolitan Transportation Authority: [MTA: Subway and bus ridership for 2024](https://web.archive.org/web/20250611222054id_/https://www.mta.info/agency/new-york-city-transit/subway-bus-ridership-2024)
- NYC Department of Homeless Services (NYC Open Data): [DHS Daily Report (Historical) — the shelter census, 21 August 2013 to 28 February 2021](https://data.cityofnewyork.us/Social-Services/DHS-Daily-Report-Historical-/dwrg-kzni)
- NYC Department of Homeless Services (NYC Open Data): [DHS Daily Report — individuals in the NYC Department of Homeless Services shelter system](https://data.cityofnewyork.us/Social-Services/DHS-Daily-Report/k46n-sa2m)
- NOAA National Centers for Environmental Information: [NOAA NCEI Global Historical Climatology Network - Daily, New York Central Park (USW00094728), by-station file](https://www.ncei.noaa.gov/products/land-based-station/global-historical-climatology-network-daily)
- U.S. Census Bureau, Population Division: [Annual Intercensal County Resident Population Estimates by Selected Age Groups and Sex, New York: April 1, 2010 to April 1, 2020](https://www.census.gov/data/datasets/time-series/demo/popest/intercensal-2010-2020-counties.html)
- U.S. Census Bureau, Population Division: [County Population Estimates by Selected Age Groups and Sex, New York: April 1, 2020 to July 1, 2025 (Vintage 2025)](https://www.census.gov/data/tables/time-series/demo/popest/2020s-counties-detail.html)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2001: Volume I](https://www.nyc.gov/assets/operations/downloads/pdf/mmr/0901_vol1.pdf)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2004](https://www.nyc.gov/assets/operations/downloads/pdf/mmr/0904_mmr.pdf)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2006](https://www.nyc.gov/assets/operations/downloads/pdf/mmr/0906_mmr.pdf)
- NYC Mayor's Office of Operations (via NYC Open Data): [FY03 - FY12 MMR Agency Performance Indicators (NYPD rows)](https://data.cityofnewyork.us/d/jhjm-vsp8)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2016: New York City Police Department chapter](https://www.nyc.gov/assets/operations/downloads/pdf/mmr2016/nypd.pdf)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2021: New York City Police Department chapter](https://www.nyc.gov/assets/operations/downloads/pdf/mmr2021/nypd.pdf)
- NYC Mayor's Office of Operations: [Mayor's Management Report, Fiscal 2026: New York City Police Department chapter](https://www.nyc.gov/assets/operations/downloads/pdf/mmr2026/nypd.pdf)
- New York State Legislature (Senate legislation API): [New York State Assembly bill A.10491 (2022): assaults upon certain employees of a transit agency or authority](https://legislation.nysenate.gov/pdf/bills/2021/A10491)
- New York State Legislature (Senate legislation API): [New York State budget bill S.8305-C / A.8805-C (2024), public protection and general government: Part A, assault on a retail worker](https://legislation.nysenate.gov/pdf/bills/2023/S8305C)
- New York State Legislature (Senate legislation API): [New York State Assembly bill A.3340 (2023): sex offenses, the definition of rape](https://legislation.nysenate.gov/pdf/bills/2023/A3340)
- New York City Police Department: [NYPD Transit Bureau (nyc.gov page)](https://www.nyc.gov/site/nypd/bureaus/transit-housing/transit-housing-landing.page)
- Office of the Governor of New York (press release, 20 March 2020; Internet Archive copy of 1 October 2026): [Governor Cuomo Signs the 'New York State on PAUSE' Executive Order](https://web.archive.org/web/20261001172636id_/https://www.governor.ny.gov/news/governor-cuomo-signs-new-york-state-pause-executive-order)
- Metropolitan Transportation Authority (press release, May 2021; Internet Archive copy of 18 May 2026): [MTA to Restore 24-Hour Subway Service on Monday, May 17](https://web.archive.org/web/20260518125938id_/https://www.mta.info/press-release/mta-restore-24-hour-subway-service-monday-may-17)
- NYC Office of the Mayor: [Mayor Adams Releases Subway Safety Plan, Says Safe Subway is Prerequisite for New York City's Recovery (press release)](https://www.nyc.gov/mayors-office/news/2022/02/mayor-adams-releases-subway-safety-plan-says-safe-subway-prerequisite-new-york-city-s)
- NYC Office of the Mayor: [Mayor Adams and Governor Hochul Announce Major Actions to Keep Subways Safe and Address Transit Crime (press release)](https://www.nyc.gov/office-of-the-mayor/news/773-22/mayor-adams-governor-hochul-major-actions-keep-subways-safe-address-transit)
- Metropolitan Transportation Authority (press release, 18 August 2023; Internet Archive copy of 18 May 2026): [REMINDER: New Fares on Subway, Buses and Commuter Railroads to Begin Aug. 20](https://web.archive.org/web/20260518223155id_/https://www.mta.info/press-release/reminder-new-fares-subway-buses-and-commuter-railroads-begin-aug-20)
- ABC (WTVD), reporting Governor Hochul's announcement: [New York governor to deploy National Guard, state police to combat NYC subway crime (ABC, 7 March 2024)](https://abc11.com/post/national-guard-new-york-subway-crime-violence-kathy-hochul/14499970/)
- Metropolitan Transportation Authority (press release, 18 November 2024; Internet Archive copy of 12 June 2026): [MTA Board Approves Phasing In the Congestion Relief Zone Toll](https://web.archive.org/web/20260612020854id_/https://www.mta.info/press-release/mta-board-approves-phasing-congestion-relief-zone-toll)
- Spectrum News NY1: [NYPD to deploy 1,050 more officers into subway stations, Hochul says (NY1, 16 January 2025)](https://ny1.com/nyc/all-boroughs/news/2025/01/16/nypd-to-deploy-1-050-more-officers-into-subway-stations--hochul-says)
- Metropolitan Transportation Authority (press release, 30 September 2025; Internet Archive copy of 21 May 2026): [MTA Board Adopts Fare and Toll Increases to Take Effect January 2026](https://web.archive.org/web/20260521053001id_/https://www.mta.info/press-release/mta-board-adopts-fare-and-toll-increases-take-effect-january-2026)

## Columns

### `subway_crime_monthly.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | Month in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM; not the month it was reported. |
| `year` | integer | observed | Calendar year. |
| `fiscal_year` | integer | derived | New York City fiscal year (July to June), named for the year it ends in. |
| `six_major` | integer | observed | Complaints 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. |
| `murder` | integer | observed | Murder 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). |
| `rape` | integer | observed | Rape complaints (the definition was widened by a law signed on 30 January 2024; see events.csv). |
| `robbery` | integer | observed | Robbery complaints: theft by force or threat. |
| `felony_assault` | integer | observed | Felony assault complaints (NYPD key code KY_CD 106), the serious grade of assault, widened in 2022 and 2024 (see felony_assault_widenings_in_force). |
| `burglary` | integer | observed | Burglary complaints. |
| `grand_larceny` | integer | observed | Grand larceny complaints, the felony grade of theft (not of a motor vehicle). |
| `felony_assault_ordinary` | integer | observed | Felony 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_strangulation` | integer | observed | Felony assaults with PD_CD 105 (strangulation). |
| `felony_assault_police_or_peace_officer` | integer | observed | Felony assaults with PD_CD 106 (on a police or peace officer). |
| `felony_assault_other_public_service_employee` | integer | observed | Felony 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_services` | integer | observed | Theft 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_felonies` | integer | observed | Every felony complaint whose premises is the subway, including offences the police mostly find themselves (weapons, drugs). |
| `all_misdemeanors` | integer | observed | Every misdemeanour complaint (dominated by enforcement in recent years). |
| `all_violations` | integer | observed | Every violation complaint. |
| `all_complaints` | integer | observed | Felonies, misdemeanours and violations. |
| `paid_rides` | integer | mixed | Paid 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_method` | string | derived | How 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_share` | number | published_estimate | The MTA's estimate of the share of entries that are unpaid, for the month's quarter (a fraction). Empty before 2018, when the MTA's estimates begin, and for April to June 2020, when none was published. |
| `unpaid_share_moe` | number | published_estimate | The MTA's published margin of error on unpaid_share (a fraction; confidence level not stated). Empty before 2020, when the MTA begins publishing margins, and for April to June 2020. |
| `entries_est` | integer | modelled | Estimated entries, paid or not: paid_rides / (1 - unpaid_share). Empty where unpaid_share is, as there is no estimate to divide by. |
| `six_major_per_m_paid` | number | derived | Six major felony complaints per million paid rides. |
| `felony_assault_per_m_paid` | number | derived | Felony assault complaints per million paid rides. |
| `robbery_per_m_paid` | number | derived | Robbery complaints per million paid rides. |
| `grand_larceny_per_m_paid` | number | derived | Grand larceny complaints per million paid rides. |
| `six_major_per_m_entries` | number | derived | Six major felony complaints per million estimated entries, paid or not. Empty where entries_est is. |
| `felony_assault_per_m_entries` | number | derived | Felony assault complaints per million estimated entries. Empty where entries_est is. |
| `robbery_per_m_entries` | number | derived | Robbery complaints per million estimated entries. Empty where entries_est is. |
| `grand_larceny_per_m_entries` | number | derived | Grand larceny complaints per million estimated entries. Empty where entries_est is. |
| `felony_assault_widenings_in_force` | integer | derived | How 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_file` | string | derived | The NYPD file the month's counts come from: historic (to December 2025) or year_to_date (2026). |
| `report_cutoff` | string | observed | The last report date in that file (YYYY-MM-DD): complaints reported after it are not in the count. |
| `late_reports_all` | integer | observed | Complaints 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 for 2026's months, whose late reports are already in their counts: not applicable, not zero. |
| `late_reports_six_major` | integer | observed | The six major felonies among late_reports_all. Empty for 2026's months: not applicable, not zero. |
| `complete` | boolean | derived | A 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `year` | integer | observed | Calendar year. |
| `six_major` | integer | observed | Complaints of the six major felonies on the subway premises in the year (grand larceny of a motor vehicle excluded). |
| `murder` | integer | observed | Murder complaints on the subway premises in the year: zero, which is not evidence that none happened (the fiscal series counts the transit system's). |
| `rape` | integer | observed | Rape complaints in the year (the definition was widened by a law signed on 30 January 2024). |
| `robbery` | integer | observed | Robbery complaints in the year. |
| `felony_assault` | integer | observed | Felony assault complaints (KY_CD 106) in the year. |
| `burglary` | integer | observed | Burglary complaints in the year. |
| `grand_larceny` | integer | observed | Grand larceny complaints in the year (not of a motor vehicle). |
| `felony_assault_ordinary` | integer | observed | Felony assaults with PD_CD 109 in the year. Not a constant-definition category: newly covered workers can sit here. |
| `felony_assault_strangulation` | integer | observed | Felony assaults with PD_CD 105 (strangulation) in the year. |
| `felony_assault_police_or_peace_officer` | integer | observed | Felony assaults with PD_CD 106 (on a police or peace officer) in the year. |
| `felony_assault_other_public_service_employee` | integer | observed | Felony assaults with PD_CD 108 (on another public service employee) in the year. |
| `theft_of_services` | integer | observed | Theft of services complaints (PD_CD 478 under key code 343) in the year: a record of enforcement, not a crime trend. |
| `all_felonies` | integer | observed | Felony complaints in the year. |
| `all_misdemeanors` | integer | observed | Misdemeanour complaints in the year. |
| `all_violations` | integer | observed | Violation complaints in the year. |
| `all_complaints` | integer | observed | Every complaint in the year. |
| `paid_rides` | integer | observed | The 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_method` | string | derived | official_total (to 2020) or daily_counts (from 2021). |
| `official_annual_total` | integer | observed | The MTA's official yearly subway ridership. Empty for 2025: the MTA's latest yearly page is for 2024. |
| `unpaid_share` | number | modelled | 1 - paid_rides / entries_est for the year: the unpaid share implied by its quarters. Empty before 2018 (no estimate) and for 2020 (none for April to June). |
| `entries_est` | integer | modelled | The year's estimated entries, added up from unrounded monthly values. Empty where any month of the year has no estimate (before 2018, and 2020). |
| `six_major_per_m_paid` | number | derived | Six major felony complaints per million paid rides in the year. |
| `felony_assault_per_m_paid` | number | derived | Felony assault complaints per million paid rides in the year. |
| `robbery_per_m_paid` | number | derived | Robbery complaints per million paid rides in the year. |
| `grand_larceny_per_m_paid` | number | derived | Grand larceny complaints per million paid rides in the year. |
| `six_major_per_m_entries` | number | derived | Six major felony complaints per million estimated entries in the year. Empty where entries_est is. |
| `felony_assault_per_m_entries` | number | derived | Felony assault complaints per million estimated entries in the year. Empty where entries_est is. |
| `robbery_per_m_entries` | number | derived | Robbery complaints per million estimated entries in the year. Empty where entries_est is. |
| `grand_larceny_per_m_entries` | number | derived | Grand larceny complaints per million estimated entries in the year. Empty where entries_est is. |
| `felony_assault_widenings_in_force` | integer | derived | The 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_incomplete` | integer | derived | How many of the year's months are flagged as not yet complete (2025: one, December). |

### `subway_ridership_monthly.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | Month (YYYY-MM). |
| `year` | integer | observed | Calendar year. |
| `quarter` | integer | observed | Calendar quarter (1-4), the period of the fare-evasion estimate. |
| `fiscal_year` | integer | derived | New York City fiscal year (July to June). |
| `paid_rides` | integer | mixed | Paid subway entries in the month: the MTA's daily figures added up from March 2020, modelled before (paid_rides_method). |
| `paid_rides_method` | string | derived | annual_total_x_2019_pattern (to December 2019), annual_total_less_daily (January and February 2020) or daily_counts (from March 2020). |
| `official_annual_total` | integer | observed | The 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 for 2025 and 2026: no official yearly figure has been published yet. |
| `unpaid_share` | number | published_estimate | The MTA's unpaid share for the month's quarter (a fraction). 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_moe` | number | published_estimate | Its published margin of error (a fraction). Empty before 2020, when the MTA begins publishing margins, and wherever unpaid_share is empty. |
| `entries_est` | integer | modelled | Estimated entries, paid or not: paid_rides / (1 - unpaid_share). Empty where unpaid_share is. |
| `entries_est_unpaid_minus_1pt` | integer | modelled | Entries 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 where unpaid_share is. |
| `entries_est_unpaid_plus_1pt` | integer | modelled | Entries with the unpaid share one percentage point (0.01) higher: a scenario, not a confidence bound. Empty where unpaid_share is. |
| `station_sum_rides` | integer | observed | The 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 before February 2017, when the MTA's station file starts, and for September 2026, after its latest month. |

### `fare_evasion_quarterly.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `period` | string | observed | Quarter (YYYY-Qn). |
| `year` | integer | observed | Calendar year. |
| `quarter` | integer | observed | Calendar quarter (1-4). |
| `unpaid_share` | number | published_estimate | Estimated share of entries that are unpaid (a fraction). Empty for 2020 Q2: no estimate was published. |
| `margin_of_error` | number | published_estimate | Published margin of error (a fraction; confidence level not stated). Empty before 2020 Q1, when the MTA begins publishing margins, and for 2020 Q2. |

### `transit_major_felonies_fiscal.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `fiscal_year` | integer | observed | New York City fiscal year (July to June), named for the year it ends in. |
| `months` | string | derived | The months the fiscal year covers (YYYY-MM to YYYY-MM). |
| `major_felonies` | integer | observed | Major 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_scope` | string | derived | What major_felonies counts: the whole transit system under the NYPD's Transit Bureau. |
| `rides_scope` | string | derived | What paid_rides counts: subway paid entries. |
| `mmr_source_id` | string | derived | The source the figure was read from (sources.csv). Where editions overlap they agree to the felony; the latest is kept. |
| `note` | string | observed | A remark the source makes about the year (fiscal 1998: based on preliminary data). Empty where the source makes no remark about the year. |
| `paid_rides` | integer | mixed | Paid 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_method` | string | derived | How the year's months were built (see subway_ridership_monthly.csv); fiscal 2020 mixes all three. |
| `major_felonies_per_m_paid` | number | derived | Transit-system major felonies per million paid subway rides: a ratio across two scopes. |
| `unpaid_share` | number | modelled | The fiscal year's implied unpaid share (1 - paid / entries). Empty before fiscal 2019 (no estimate for every month) and for fiscal 2020 (none for April to June 2020). |
| `entries_est` | integer | modelled | Estimated subway entries, paid or not, in the fiscal year. Empty where unpaid_share is. |
| `major_felonies_per_m_entries` | number | derived | Transit-system major felonies per million estimated subway entries. Empty where entries_est is. |

### `subway_crime_daily.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `date` | string | observed | The day the recorded offence began (CMPLNT_FR_DT), YYYY-MM-DD. |
| `year` | integer | observed | Calendar year. |
| `month` | string | observed | YYYY-MM, the key to the monthly files. |
| `day_of_week` | string | derived | Monday to Sunday. |
| `weekend` | boolean | derived | True on Saturday and Sunday. Public holidays are not flagged. |
| `six_major` | integer | observed | Complaints of the six major felonies that began that day. |
| `felony_assault` | integer | observed | Felony assault complaints that began that day. |
| `robbery` | integer | observed | Robbery complaints that began that day. |
| `grand_larceny` | integer | observed | Grand larceny complaints that began that day. |
| `all_felonies` | integer | observed | Felony complaints that began that day. |
| `all_misdemeanors` | integer | observed | Misdemeanour complaints that began that day. |
| `all_violations` | integer | observed | Violation complaints that began that day. |
| `all_complaints` | integer | observed | Every subway complaint that began that day. |
| `theft_of_services` | integer | observed | Theft of services complaints (PD_CD 478 under key code 343): a record of enforcement. |
| `paid_rides` | integer | observed | The MTA's subway ridership figure for the day, which it labels 'Total Estimated Ridership' and builds from its fare-system counts. Empty before 1 March 2020, when the MTA's daily figures begin. |
| `tmax_f` | integer | observed | Central Park's maximum temperature, whole degrees Fahrenheit (NOAA's Global Historical Climatology Network - Daily). |
| `tmin_f` | integer | observed | Central Park's minimum temperature, whole degrees Fahrenheit. |
| `precip_in` | number | observed | Central Park's precipitation (rain and melted snow), inches. |
| `snow_in` | number | observed | Central Park's snowfall, inches. |
| `felony_assault_widenings_in_force` | integer | derived | How many expansions of felony assault were in force that day (0 to 3; events.csv). |
| `complete` | boolean | derived | The 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | YYYY-MM of the day the offence began. |
| `day_type` | string | derived | weekday (Monday to Friday) or weekend (Saturday and Sunday). |
| `hour` | integer | observed | The 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_major` | integer | observed | Complaints of the six major felonies that began in the hour. |
| `felony_assault` | integer | observed | Felony assault complaints that began in the hour. |
| `robbery` | integer | observed | Robbery complaints that began in the hour. |
| `grand_larceny` | integer | observed | Grand larceny complaints that began in the hour. |
| `all_felonies` | integer | observed | Felony complaints that began in the hour. |
| `all_complaints` | integer | observed | Every subway complaint that began in the hour. |
| `all_complaints_on_the_hour` | integer | observed | Complaints whose recorded start time is exactly on the hour (HH:00:00): a measure of rounding in the times. |
| `complete` | boolean | derived | The 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `complex_id` | integer | observed | The MTA's station complex id (Complex ID in its station list, station_complex_id in its ridership). |
| `station_complex` | string | observed | The complex's current name, with the routes that stop there, as the MTA's ridership names it. |
| `borough` | string | observed | The complex's borough, as the MTA gives it. |
| `latitude` | number | observed | The complex's latitude (MTA, current). |
| `longitude` | number | observed | The complex's longitude (MTA, current). |
| `year` | integer | observed | Calendar year of the complaints. |
| `months` | integer | derived | Months of complaints the year covers: 12, or 6 for 2026 (January to June). |
| `months_incomplete` | integer | derived | How many of the year's months are flagged as not yet complete in the monthly table (2025: December; 2026: June). |
| `six_major` | integer | observed | Complaints 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_assault` | integer | observed | Felony assault complaints matched to the complex. |
| `robbery` | integer | observed | Robbery complaints matched to the complex. |
| `grand_larceny` | integer | observed | Grand larceny complaints matched to the complex. |
| `all_felonies` | integer | observed | Felony complaints matched to the complex. |
| `all_complaints` | integer | observed | Every complaint matched to the complex. |
| `all_complaints_matched_by_name` | integer | derived | Of 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. |
| `rides` | integer | observed | The MTA's entries at the complex over the same months (MTA Subway Station Monthly Ridership). 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_months` | integer | derived | Months 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_rides` | number | derived | Six major felony complaints per million entries at the complex. 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_rides` | number | derived | Felony assault complaints per million entries at the complex. Empty where the entries do not cover every month of the year's complaints. |
| `robbery_per_m_rides` | number | derived | Robbery complaints per million entries at the complex. Empty where the entries do not cover every month of the year's complaints. |
| `all_complaints_per_m_rides` | number | derived | Every complaint per million entries at the complex. Empty where the entries do not cover every month of the year's complaints. |

### `subway_station_crosswalk.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `station_name` | string | observed | The station name the NYPD records (STATION_NAME), as printed; '(null)' where blank. |
| `borough` | string | observed | The borough the NYPD records (BORO_NM). |
| `latitude` | number | observed | The latitude the NYPD records. |
| `longitude` | number | observed | The longitude the NYPD records. |
| `complaints` | integer | observed | Complaints 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_id` | integer | derived | The MTA station complex the place is matched to. |
| `matched_station` | string | observed | The MTA station (stop name) the match was made to. |
| `distance_m` | number | derived | Metres from the recorded place to that station. |
| `match` | string | derived | name: 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | Month in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM. |
| `law_category` | string | observed | FELONY, MISDEMEANOR or VIOLATION (LAW_CAT_CD). |
| `offence` | string | observed | The 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_six` | boolean | derived | One of the six major felonies (grand larceny of a motor vehicle excluded). |
| `complaints` | integer | observed | Number of complaints in this month, law category and offence. |
| `complaint_file` | string | derived | historic or year_to_date: the NYPD file the counts come from. |
| `report_cutoff` | string | observed | The last report date in that file (YYYY-MM-DD). |
| `complete` | boolean | derived | The 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | Month in which the recorded offence began (CMPLNT_FR_DT), as YYYY-MM. |
| `key_code` | integer | observed | The NYPD's key offence code (KY_CD), e.g. 105 robbery, 106 felony assault, 109 grand larceny, 343 other offences related to theft. |
| `offence` | string | observed | The offence description (OFNS_DESC) as printed; a label can change over the years while the codes do not. |
| `pd_code` | integer | observed | The NYPD's internal offence code (PD_CD), e.g. 109 ordinary felony assault, 478 theft of services, 475 unauthorised sale of transit service. |
| `pd_description` | string | observed | The internal code's description (PD_DESC) as printed. |
| `complaints` | integer | observed | Number of complaints in this month and offence-code group. |
| `complaint_file` | string | derived | historic or year_to_date: the NYPD file the counts come from. |
| `report_cutoff` | string | observed | The last report date in that file (YYYY-MM-DD). |
| `complete` | boolean | derived | The 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `year` | integer | observed | Calendar year the offence began. |
| `law_category` | string | observed | FELONY, MISDEMEANOR or VIOLATION. |
| `offence` | string | observed | The offence description (OFNS_DESC) as printed. |
| `victim_age_group` | string | observed | VIC_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_sex` | string | observed | VIC_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. |
| `complaints` | integer | observed | Number of complaints in this year, law category, offence and victim group. |
| `months_incomplete` | integer | derived | How many of the year's months are flagged as not yet complete in the monthly table. |

### `subway_report_delay_annual.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `year` | integer | observed | Calendar year the offence began. |
| `offence_group` | string | derived | rape, robbery, felony_assault, burglary, grand_larceny (the five major felonies the records hold), or other_felonies, misdemeanors, violations. |
| `lag_band` | string | derived | same day, 1 day, 2-7 days, 8-30 days, 31-90 days, 91-365 days, over a year. |
| `lag_days_min` | integer | derived | The band's shortest delay in days. |
| `lag_days_max` | integer | derived | The band's longest delay in days. Empty for 'over a year', which has no upper limit. |
| `complaints` | integer | observed | Complaints reported with that delay (RPT_DT minus CMPLNT_FR_DT), among those in the monthly table. |
| `report_cutoff` | string | observed | The last report date the year's file holds: a longer delay than this allows cannot appear yet. |
| `months_incomplete` | integer | derived | How many of the year's months are flagged as not yet complete in the monthly table. |

### `transit_arrests_monthly.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | Month of the arrest (ARREST_DATE), YYYY-MM. |
| `law_category` | string | observed | LAW_CAT_CD as printed: F felony, M misdemeanour, V violation, I infraction, and a few other codes the file holds. Empty where the NYPD's arrest file is blank. |
| `key_code` | integer | observed | Key offence code (KY_CD) of the charge. Empty where the NYPD's arrest file is blank. |
| `offence` | string | observed | Offence description (OFNS_DESC) as printed. Empty where the NYPD's arrest file is blank. |
| `pd_code` | integer | observed | Internal offence code (PD_CD); 478 under key code 343 is theft of services. Empty where the NYPD's arrest file is blank. |
| `pd_description` | string | observed | Internal code description (PD_DESC) as printed. Empty where the NYPD's arrest file is blank. |
| `arrests` | integer | observed | Number of arrests in this month, law category and charge. |

### `city_context_monthly.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `month` | string | observed | YYYY-MM (the month an offence began for complaints, the month of arrest for arrests). |
| `city_six_major` | integer | observed | Complaints 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_assault` | integer | observed | Felony assault complaints anywhere in the city. |
| `city_robbery` | integer | observed | Robbery complaints anywhere in the city. |
| `city_grand_larceny` | integer | observed | Grand larceny complaints anywhere in the city (not of a motor vehicle). |
| `city_all_complaints` | integer | observed | Every complaint anywhere in the city. |
| `subway_share_of_city_six_major` | number | derived | The monthly table's six_major divided by city_six_major. |
| `nyc_population` | integer | published_estimate | The five boroughs' population on 1 July of the month's year (Census Bureau estimates). Repeated on every month of its year. Empty for 2026: the Census Bureau's estimate for 1 July 2026 comes out in 2027. |
| `bus_six_major` | integer | observed | Six major felony complaints whose premises is a New York City Transit bus. |
| `bus_felony_assault` | integer | observed | Felony assault complaints on New York City Transit buses. |
| `bus_all_complaints` | integer | observed | Every complaint on New York City Transit buses. |
| `bus_stop_and_terminal_complaints` | integer | observed | Every complaint at bus stops and bus terminals. |
| `bus_rides` | integer | observed | The 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 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_arrests` | integer | observed | Transit-jurisdiction arrests in the month (transit_arrests_monthly.csv added up). |
| `transit_arrests_felony` | integer | observed | Transit-jurisdiction arrests on a felony charge in the month. |
| `transit_arrests_theft_of_services` | integer | observed | Transit-jurisdiction arrests for theft of services (PD_CD 478 under key code 343) in the month. |
| `shelter_individuals` | integer | observed | People 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_days` | integer | derived | Days in the month with a census (some days are missing in 2013-2021). |
| `complete` | boolean | derived | The 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `date` | string | observed | The event's date at the precision the source gives: YYYY, YYYY-MM or YYYY-MM-DD. Read it as text. |
| `date_basis` | string | derived | What 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). |
| `kind` | string | derived | law, policing_announcement, service (a change to service or fares) or data. |
| `event` | string | observed | What happened. |
| `bearing` | string | derived | What it means for reading the series. |
| `source_id` | string | observed | The source's id in sources.csv. |

### `subway_complaint_records.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `complaint_date` | string | observed | The day the offence began (CMPLNT_FR_DT), YYYY-MM-DD. |
| `complaint_time` | string | observed | The time it began (CMPLNT_FR_TM), HH:MM:SS, as recorded: often rounded to the hour, and 00:01 is a common default. |
| `end_date` | string | observed | The day it ended, where the complaint records an end (CMPLNT_TO_DT), YYYY-MM-DD. Empty where the NYPD's file is blank: no end recorded. |
| `end_time` | string | observed | The time it ended (CMPLNT_TO_TM), HH:MM:SS. Empty where the NYPD's file prints (null): no end time recorded. |
| `report_date` | string | observed | The day it was reported (RPT_DT), YYYY-MM-DD. |
| `year` | integer | derived | Calendar year of complaint_date. |
| `month` | string | derived | YYYY-MM of complaint_date, the key to the monthly files. |
| `day_of_week` | string | derived | Monday to Sunday, of complaint_date. |
| `hour` | integer | derived | The hour of complaint_time, 0 to 23. |
| `report_delay_days` | integer | derived | Days from complaint_date to report_date. |
| `law_category` | string | observed | FELONY, MISDEMEANOR or VIOLATION (LAW_CAT_CD). |
| `offence` | string | observed | The offence description (OFNS_DESC) as printed, spelling included. Empty where the NYPD's file prints (null): no description, though the codes are there. |
| `key_code` | integer | observed | The key offence code (KY_CD). |
| `pd_code` | integer | observed | The internal offence code (PD_CD). |
| `pd_description` | string | observed | The internal code's description (PD_DESC) as printed. |
| `is_major_six` | boolean | derived | One of the six major felonies (grand larceny of a motor vehicle excluded), as in the monthly table. |
| `attempted_or_completed` | string | observed | ATTEMPTED or COMPLETED (CRM_ATPT_CPTD_CD). |
| `jurisdiction` | string | observed | The jurisdiction responsible (JURIS_DESC): N.Y. TRANSIT POLICE for almost every subway complaint. |
| `precinct` | integer | observed | The precinct of the place (ADDR_PCT_CD). |
| `borough` | string | observed | The borough (BORO_NM). Empty where the NYPD's file prints (null). |
| `patrol_borough` | string | observed | The NYPD patrol borough (PATROL_BORO). |
| `transit_district` | integer | observed | The NYPD transit district (TRANSIT_DISTRICT). Empty where the NYPD's file is blank. |
| `station_name` | string | observed | The station name the NYPD records (STATION_NAME), as printed. Empty where the NYPD's file prints (null). |
| `latitude` | number | observed | The latitude the NYPD records. |
| `longitude` | number | observed | The longitude the NYPD records. |
| `complex_id` | integer | derived | The MTA station complex the place is matched to (subway_station_crosswalk.csv). |
| `station_match` | string | derived | How surely the place was matched: name, name_far, distance or uncertain, as in the station-matching table. |
| `victim_age_group` | string | observed | The 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 where the NYPD's file prints (null); not the same as UNKNOWN, which the NYPD recorded. |
| `victim_sex` | string | observed | The 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_group` | string | observed | The 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 where the NYPD's file prints (null); not the same as UNKNOWN, which the NYPD recorded. |
| `suspect_sex` | string | observed | The suspect's sex as recorded (SUSP_SEX): F female, M male, U unknown. Empty where the NYPD's file prints (null); U is a recorded value, not an empty cell. |
| `complaint_file` | string | derived | historic or year_to_date: the NYPD file the complaint is in. |
| `report_cutoff` | string | observed | The last report date in that file (YYYY-MM-DD): complaints reported after it are not here. |
| `late_report` | boolean | derived | True 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`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `file` | string | derived | CSV file name. |
| `column` | string | derived | Column name. |
| `rows` | integer | derived | Rows in the file. |
| `empty` | integer | derived | Empty cells in the column. |
| `share_empty` | number | derived | empty / rows. |
| `why_empty` | string | derived | Why the cells are empty. |

### `data_dictionary.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `file` | string | derived | The file the column is in. |
| `column` | string | derived | The column's name. |
| `type` | string | derived | string, integer, number or boolean. |
| `class` | string | derived | How 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. |
| `layer` | string | derived | The licence layer that applies: government (the publisher's terms), derived (SparkyData's, CC BY 4.0) or mixed (by row). |
| `description` | string | derived | What the column holds, and why it can be empty. |

### `sources.csv`

| Column | Type | Class | Description |
| --- | --- | --- | --- |
| `source_id` | string | derived | The source's id, as events.csv and transit_major_felonies_fiscal.csv cite it. |
| `publisher` | string | observed | Who publishes it. |
| `title` | string | observed | Its title. |
| `landing_page` | string | observed | The page that describes it. |
| `url` | string | observed | The address it was fetched from (for open-data tables, the query that counted the records). |
| `retrieved_utc` | string | observed | When it was fetched, in Coordinated Universal Time (a date can differ by one from a local date). |
| `sha256` | string | observed | The SHA-256 checksum of the saved copy, to verify the file. |
| `saved_as` | string | derived | The saved copy's path in SparkyData's repository (data/raw is a cache; data/reference is kept). |
| `locator` | string | derived | Where in the source the figures used are (an indicator, a chart, a clause). Empty where no locator is needed: the figures come from the whole table, or the whole document. |
| `terms` | string | observed | The terms the source is published under, as recorded at retrieval. |

## Versions

- **1.0** (2026-10-18): First release.
- **1.1** (2026-10-19): 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** (2026-10-19): 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.

## Contact

Corrections and questions: sparkytech.dev@gmail.com, or https://sparkydata.dev/corrections.
