30DayMapChallenge Day 01 - Points

First look at working with maps in Python
30DayMapChallenge
Data visualization
Python
Geospatial
Author

Seth Kasowitz

Published

November 1, 2025

The #30DayMapChallenge may happen every November, but it still managed to completely sneak up on me. The first day’s challenge asks us to create a map with point data, and I decided to

1 Setup

Show the code
import json
import pandas as pd
import geopandas as gpd
from geodatasets import get_path

from arcgis.gis import GIS
from arcgis.features import FeatureLayer

gis = GIS()

2 Retrieve Data

Show the code
polling_locs = gis.content.get('23a056702cfd40848deef9597945a998')

This Feature Layer Collection has 5 layers

Show the code
for feature_layer in polling_locs.layers:
    print(feature_layer.properties.name)
Early Voting Polling Sites Non NYC 
Early Voting Polling Sites NYC 
Election Day Polling Sites Non NYC 
Election Day Polling Sites NYC
Election Districts

For this map I decided to look at the NYC Election Day polling locations. First, retrieve the data with a query on the FeatureLayer.

Show the code
nyc_election_day_url = 'https://services6.arcgis.com/EbVsqZ18sv1kVJ3k/arcgis/rest/services/NYS_Elections_Districts_and_Polling_Locations/FeatureServer/3'
nyc_election_day = FeatureLayer(nyc_election_day_url)
polling_sites = nyc_election_day.query()
polling_sites
<FeatureSet> 1212 features

Next, preparing the data for plotting by creating a geopandas.GeoDataFrame.

Show the code
polling_sites_gjson = polling_sites.to_geojson
polling_sites_dict = json.loads(polling_sites_gjson)
polling_sites_gdf = gpd.GeoDataFrame.from_features(polling_sites_dict['features'])
polling_sites_gdf.head()
geometry OBJECTID Poll_Site_Name Poll_Site_Address City ZipCode County NYS_Latitude NYS_Longitude
0 POINT (592646.639 4526000.831) 1 Ft. Independence Community Center 3350 Bailey Avenue Bronx 10463 Bronx 40.879846 -73.900400
1 POINT (591752.532 4525907.066) 2 In Tech High School (MS/HS 368) 2975 Tibbett Avenue Bronx 10463 Bronx 40.879102 -73.911024
2 POINT (592321.697 4518947.062) 3 St. Anselm School 685 Tinton Avenue Bronx 10455 Bronx 40.816350 -73.905302
3 POINT (587021.407 4492206.798) 4 Neshama Community Services 301 Seabreeze Avenue Brooklyn 11224 Kings 40.576073 -73.971849
4 POINT (594951.145 4503973.588) 5 PS IS 667 76 Dinsmore Place Brooklyn 11208 Kings 40.681186 -73.876401

3 Make a Map

Lat and Long to point geometry. I couldn’t ftell out what coordinate system the NYS data is using, so guessed EPSG: 4326. Converted so the data could plot over a map of the NYC boroughs.

Show the code
polling_gdf = gpd.GeoDataFrame(polling_sites_gdf, geometry = gpd.points_from_xy(polling_sites_gdf.NYS_Longitude, polling_sites_gdf.NYS_Latitude), crs="EPSG:4326")
polling_gdf.head()
# Convert coordinate system
polling_gdf = polling_gdf.to_crs('EPSG:2263')
Show the code
# Get borough boundaries
path_to_data = get_path("nybb")
nybb_dat = gpd.read_file(path_to_data)
nybb_dat = nybb_dat.set_index("BoroName")
nybb_dat["boundary"] = nybb_dat.boundary
Show the code
# Draw the map
ax = nybb_dat["boundary"].plot()
ax.set_axis_off()
polling_gdf["geometry"].plot(
    figsize=(12, 12),
    ax=ax,
    color="black",
    markersize=1
).set_title("NYC Election Day Polling Sites: 2025")
Text(0.5, 1.0, 'NYC Election Day Polling Sites: 2025')

Citation

BibTeX citation:
@online{kasowitz2025,
  author = {Kasowitz, Seth},
  title = {30DayMapChallenge {Day} 01 - {Points}},
  date = {2025-11-01},
  url = {https://sethkasowitz.com/posts/2025-11-01_30DayMapChallenge_Day01/},
  langid = {en}
}
For attribution, please cite this work as:
Kasowitz, Seth. 2025. “30DayMapChallenge Day 01 - Points.” November 1, 2025. https://sethkasowitz.com/posts/2025-11-01_30DayMapChallenge_Day01/.