Sharing NYC Police Precinct Data

Note: This post was originally published April 29, 2011, and updated in June 2020. In February 2022, I updated it again using 2020 Census data. 

Anyone doing population analysis by NYC police precinct might find this post helpful, especially if you're interested in race and/or ethnicity analysis by precinct.

Back in 2011, I wanted to compare the racial and ethnic breakdown of low-level marijuana arrests — reported by police precinct — with that of the general population. The population data, of course, is available from the US Census, but it's not provided by police precincts, which also don't follow any major census boundaries like census tracts. Instead, they generally follow streets and shorelines. Fortunately, census blocks (which in New York, are often just city blocks) also follow streets and shorelines.

So I used US Census block maps and precinct maps from the city to figure out which blocks are in which precincts. Since population data is available at the block level, that data can then be aggregated into precincts.

In this, the third version of this post, I've updated the counts now that the 2020 population data is available.

The 2020 data

• nyc_precinct_2020pop.csv is the 2020 Census population, race, and ethnicity (Hispanic/non-Hispanic) data by NYPD police precinct. The column headers from the US Census are a little cryptic, but you can translate them using the P1 table metadata file and the P2 table metadata file.

nyc_block_precinct_2020pop.csv — every populated block in NYC is identified by its ID (called "GEOID20"), is matched to the police precinct it sits within, and contains the block's race/ethnicity information. Use the same metadata tables to translate the column headers. Also be sure to read about the caveats below.

nyc_precincts.geojson depicts the geographic boundaries of the NYPD precincts I used for the files above, as they existed in February 2022. As of this post, the information on the NYC Open Data portal indicates it was last updated on Nov 24, 2021.

Caveats for the 2020 data

The biggest caveat is that the US Census has introduced data fuzziness, or "noise," to make it difficult to identify individuals based on census data. This fuzziness is more pronounced at smaller geographies — the smallest being census blocks, which I've used for these calculations. Hansi Lo Wang did a great primer on these data protections for NPR, and the US Census Bureau has put out a lot of material on how it uses "differential privacy."

I have not determined if and how this fuzziness affects the calculations I've done by police precinct. My general understanding is that, since I'm aggregating many blocks — almost 40,000 of them — into 77 police precincts, the error will wash away or be insignificant. But I don't know that for certain (if you have more insight, please let me know!) The data for an individual block, however, I do think should be treated with caution.

Separately, there are two apparently inhabited Bronx blocks that straddle two police precincts — and I've placed them entirely in one or the other. Block number 360050334001003 is said to contain 50 residents, though it is comprised entirely of parkland called the Bronx River Forest. It straddles the 47th and 49th precincts, and I've placed it in the 47th. Block 360050096002000 appears to be entirely commercial, but is said to have 33 residents. It straddles the 45th and 43rd precincts, and I've placed it in the 45th. 

My methods

My calculations and code are posted in a GitHub repository, and I welcome you to use and review it. The main components are a Makefile and a Python Jupyter notebook.

On issuing the command make all, the Makefile downloads the census block geographic files from the US Census Bureau and the precincts from the New York City data portal. It then uses the census' block centroids to place each block within a police precinct and generates files used in the notebook. If you try it on your own, be sure to change the "mypath" variable in the Makefile and the notebook to the full path of a directory where you want to store the files.

I also generate a couple of "confidence check" files that allow me to use the QGIS open-source mapping program to visually check at how the calculations line up. I color the blocks by precinct number and then layer the precinct boundaries on top to see where any of the colors cross (that is the map atop this post).

There were, in fact, 43 blocks that didn't fall into precincts — largely because their centroids fell outside the precinct lines. Only 9 of those were actually populated, and I manually updated the precincts for those blocks.

The population data is available from the census data site, which takes some navigating.

In the end, I generated and downloaded the P1 race table and the P2 Hispanic/non-Hispanic table from the 2020 census for the five counties that make up New York City.

Once I had the blocks connected to precincts, and the population data attached to the blocks, a basic pivot table gave me the final results.

The 2010 data, archived

For anyone needing the 2010 files, I'm archiving the materials from my original posts here. This is, to be clear, based on the 2010 census, and is not the latest data available.

The original stories I did this for, and the Google Fusion Tables where the data lived, are all gone to digital internet history. But I've recreated them here. Some precinct boundaries changed slightly from 2011, and those on Staten Island changed significantly with the addition of a fourth precinct on the island in 2013.

2010pop_2020precincts.csv is the 2010 population breakdown within each precinct as they are drawn in June 2020. The column headings are cryptic, but follow the codes starting on this page, which is from this rather large Census Bureau PDF.  

• precinct_block_key_2020.csv is the Rosetta Stone for this project. It has two columns: each block's identifier, which the census calls "geoid10," and the precinct in which that block sits. Note that some blocks aren't in any precinct, usually because they're actually in the water. 

• nyc_2010censusblocks_2020policeprecincts.csv contains base-level 2010 Census data for each block, married to the precinct for that block. For descriptions of the population columns, follow the codes starting on this page or see pages 6-21 in the Census Bureau PDF

• is the police precinct map shapefile, downloaded from the city's open data portal, as those boundaries stood when I made these calculations in June 2020.

Caveats for the 2010 data

I did my best to be accurate in computing the intersection of blocks and precincts, even generating precinct maps and inspecting them visually. But errors may exist. You can check my math in the Jupyter notebooks I used.

Census blocks generally fall nicely within precinct outlines, but they don't always. In particular, three blocks significantly straddle two precincts. If you're doing very precise analysis, you'll want to account for them:

• Block 360470071002003: An area near the north end of the Gowanus Canal in Brooklyn. About half is in Precinct 76 and half in Precinct78. Total people: 51

• Block 360050096002000: Mainly industrial. Half in Precinct 76, half in Precinct 78. Total people: 5.

• Block 360610265003001: This block consists of five similar-sized apartment buildings near the George Washington Bridge. The northern set of buildings are in the 34th Precinct, with part of one building in the 33rd. I put the entire block, and the 687 people living there, in the 34th Precinct. Looks like roughly an 80/20 split.


I originally did this work while at WNYC, using PostgreSQLPostGIS and QGIS. I was helped by the generosity and insights of Jeff Larson, Al Shaw, and Jonathan Soma. The 2020 data is assembled mainly using the great Mapshaper tool by Matthew Bloch.

If you find this information useful, find a bug, or know how the new census data-fuzzing might affect these calculations flag me on Twitter @jkeefe. I'd love to hear from you.

17 responses
John, great work as always. When you aggregated the block data to precincts, did you compute intersections or use a centroid approach? I find that the centroid approach is much cleaner, easier, and -- except for the "straddlers" as you point out above -- more consistent in terms of allocating small-area population to larger spatial units. (I've been meaning to post something about this, your blog gives me more impetus to do so -- we've been dealing with this extensively at our shop at the CUNY Graduate Center as well.)


Yes! I tried both methods and experienced the same thing. I actually used the "internal point" latitude and longitude provided by the Census Bureau, which should be even better than a simple centroid. Since the precincts seem to have been drawn around the blocks for the most part, it worked really nicely -- and the "straddlers" were easy to spot.
Hey John,

Cool stuff - it's great to see you share the data and methodology for this stuff.

You could make the (possibly incorrect, especially in rural areas) assumption that people are evenly spaced within the census blocks, and then assign the appropriate numbers to each arbitrary polygon by using the block shapes rather than centroids. The general methodology for this would be to:
- Calculate the percentage intersection of each census block to each polygon
- Multiply the total block population by that percentage
- Sum these partial populations of each block to get the total polygon population [or other attribute]

Assuming your data is unprojected (e.g. epsg:4326) and you want more easily readable areas to look at, then in PostGIS land your query might look something like:
SELECT b.population,
area(b.the_geom) * 100000000 as area,
area(st_intersection(b.the_geom, p.the_geom) *
100000000 as intersected_area
FROM precincts p, blocks b
WHERE st_intersects(b.the_geom, p.the_geom)
--and p.gid = 1234 -- [for some specific precinct]
GROUP by p.gid, b.population, intersected_area, area

Note that all we care about is relative area, not actual area (area calculations don't really make sense in unprojected reference systems; I just multiplied by a big number to make the result more easily readable).



Josh, thanks so much for this! I was actually heading down this path when I switched back to the centroid method -- partly because I wasn't sure how to pull off this area calculation, and also because there were only three blocks that really came up as an issue -- and I could get a sense of them visually in Google Maps.

One REALLY BIG thing to consider is that you can have problems when much of the area in question falls over water -- which is common for Census *tracts* on shorelines. For example, in Manhattan, there are tracts that have slivers of densely populated areas along the water, and with the bulk of the tract in the Hudson River! That's because the tracts extend to the state line, which is in the water.

A way around that is to consider the tract's AREAWATR and AREALAND metadata values, provided by the Census Bureau, in the calculation.

Better yet, use blocks, which end at the shorelines. (Other, watery blocks -- with 0 AREALAND -- fill out the tracts to the state line.)

Hi John. Thanks for sharing this tool with the public. I have a question: in doing this research, did you ever figure out how the NYPD precinct lines were actually drawn? I work for a non-profit that serves troubled youth, and we have several locations across the city. I'm trying to compare crime stats in each of the communities we serve, so it would be helpful for me to know how the our precinct llines were created (by population, by census, by geography). I've made several calls to the NYPD, and the answer has been "they've been like that forever." Just wondering if you might have come across the answer in the course of your work. Best, Denise
Hi John, I'm working on a mental health disparities project comparing neighborhood characteristics and I was wondering where/how you accessed precinct level crime data for NYC. I've been scouring NYC OpenData as well as the NYPD website and can't seem to find anything at the precinct level, much less anything broken down by specific crimes. Any advice or sources would be greatly appreciated.
Hi John, I've been trying to download the dataset but not been successful.... and the aggregate function seems to be not working,,, i've tried on a number of computers... but can't figure out how I can make it work... any thoughts? or suggestions?
john -- having worked so hard to compile pop by census block and precinct by census block, couldn't you have written a pretty basic summation program to get pop by precinct, without the magic of google? that aside, why not add a table of the 124 totals, for the use of peons lacking the time to emulate your google mastery? such people do matter, and giving them access would make your labors exponentially more worthwhile. just saved me. thank you for this gem!
What is the population of the Sixth Precinct? Erich Goode
John: Thanks so much for supplying statistics on the racial composition for the Sixth Precinct as a whole; this is very useful. Is it possible to designate an area within a certain ambit of Washington Square Park (say, 10 blocks) & find out the racial characteristics that area? I realize this would be a very custom-made statistic, but is it a simple matter to figure this out? Erich Goode
Hi John, these statistics are amazing and invaluable to doing public policy research. I am doing a project on gun crime that takes into account population density, but I am having a hard time getting data on the size of the precincts. Can you tell me what the GIS data is in for the precinct sizes? GIS Area is usually just supplied in whatever form someone makes it in, but doesn't display. Do you have any idea what units the GIS data is in?
Cohesive and correct. Thank you so much for the time saver.
Hi John. I'm having trouble accessing the precinct_block_key.csv file that you linked to above. Is this still available for download? Thanks for building this great tool!
Hi John, This looks amazing! I am currently working on a project that needs to aggregate census tracts to precinct levels. However, when i downloaded the data from the American Community Survey, my tracts were labeled as "Census Tract 556, Kings County, New York" not the longer numerical names, as outlined in your files. Did i do something incorrectly? Is there a way to figure out which tracts belong into which precinct, or is this something that I will have to do manually with maps?
Thanks so much John, this key was a big help!
Great work. I didn't notice if there was there income data included...