Public parks in San Francisco¶

This notebook attempts to locate all the public parks in San Francisco. One of my goals in 2025 is to visit every park in the city.

I figure it'd be too difficult to rigorously do this from google maps on my phone, so I reached for openstreetmaps and the associated ecosystem. It did not disappoint!

This notebook was used to gather the data for https://parks.dxuuu.xyz/.

In [110]:
import osmnx
import folium

tags = {
    'leisure': 'park',
    # Could also include: 'garden', 'nature_reserve' depending on your needs
}

sf_boundary = osmnx.geocode_to_gdf("San Francisco, California")

parks = osmnx.features_from_polygon(
    sf_boundary.geometry.iloc[0],
    tags=tags
)
parks
Out[110]:
geometry ele gnis:feature_id leisure name wikidata wikipedia historic opening_hours smoking ... leaf_type acres communication:amateur_radio:pota name:pt tourism fee location type disused:landuse source:operator
element id
node 358767175 POINT (-122.49088 37.72237) 16 224922 park Harding Park Q49497924 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803650 POINT (-122.40303 37.79687) 7 1655668 park Jackson Square Historic District Q49506269 NaN district NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803668 POINT (-122.49942 37.72549) 8 1655678 park Lake Merced Sports Center NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803681 POINT (-122.41367 37.72248) 55 1655685 park Louis Sutter Playground Q49519583 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803706 POINT (-122.37692 37.72965) 56 1655701 park Milton Myer Recreation Center Q49526782 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
way 1286999777 POLYGON ((-122.39559 37.79113, -122.3952 37.79... NaN NaN park Urban Park NaN NaN NaN Mo-Fr 08:00-20:00 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1293746220 POLYGON ((-122.47178 37.75073, -122.47106 37.7... NaN NaN park Mandalay Lane Park NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1293746848 POLYGON ((-122.48591 37.75188, -122.4818 37.75... NaN NaN park Sunset Reservoir Park NaN NaN NaN 24/7 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1300623937 POLYGON ((-122.44574 37.75953, -122.44508 37.7... NaN NaN park Al's Park NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1329130170 POLYGON ((-122.38623 37.7696, -122.38616 37.76... NaN NaN park Bayfront Park NaN NaN NaN sunrise-sunset NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

340 rows × 98 columns

In [111]:
park_names = parks['name'].tolist()
park_names
Out[111]:
['Harding Park',
 'Jackson Square Historic District',
 'Lake Merced Sports Center',
 'Louis Sutter Playground',
 'Milton Myer Recreation Center',
 'Rolph-Nicol Playground',
 'Farallon Islands State Game Refuge',
 'Bush Street-Cottage Row Historic District',
 'Russian Hill-Vallejo Street Crest Historic District',
 'Ulrich Field',
 'Benedetti Diamond',
 'Fairy Circle',
 'Secret Garden',
 'Annie St Plaza',
 'Maritime Plaza',
 'Lands End',
 'China Beach',
 "Saint Mary's Park",
 'Presidio of San Francisco',
 'Lincoln Park',
 'Salesforce Park',
 'Brotherhood-Head Mini Park',
 'Sue Bierman Park',
 'Mount Davidson Park',
 'Buena Vista Park',
 'McCoppin Square',
 'Panhandle',
 'Alta Plaza Park',
 'Lafayette Park',
 'Bernal Heights Park',
 'Holly Park',
 'Marina Green',
 'Washington Square Park',
 'South Beach Park',
 'Jackson Park',
 'Mission Dolores Park',
 'Rolph Playground',
 'Precita Park',
 'Sydney G. Walton Square',
 'South Park',
 'Garfield Square',
 'Potrero Del Sol Park',
 'Franklin Square',
 'McKinley Square',
 'Balboa Park',
 'Duboce Park',
 'Moscone Recreation Center',
 'Kid Power Park',
 'Union Square',
 "Levi's Plaza",
 'Tank Hill',
 'Grattan Playground',
 'Embarcadero Plaza',
 'Warm Water Cove Park',
 'Esprit Park',
 'Mission Creek Park',
 'Minnesota Grove',
 'China Basin Park',
 'Juri Commons',
 "Patricia's Green",
 'India Basin Shoreline Park',
 "Heron's Head Park",
 'Tulare Park',
 'John McLaren Park',
 "Saint Mary's Square",
 'Yerba Buena Gardens',
 'The Crossing at East Cut',
 'Silver Terrace Playground',
 nan,
 'Music Concourse',
 'Aquatic Park Historic District',
 'Marini Plaza',
 'Rincon Park',
 nan,
 'Huntington Park',
 'Boeddeker Park',
 nan,
 'Kite Hill Open Space',
 'Willie "Woo Woo" Wong Park',
 'Sergeant John Macaulay Park',
 'Joe DiMaggio Playground',
 'Glen Canyon Park',
 'Cottage Row Mini Park',
 'Baker & Broderick Mini Park',
 'Turk-Hyde Mini Park',
 'Sunset Tunnel Park',
 'Excelsior Playground',
 'Palega Recreation Center',
 'Candlestick Point State Recreation Area',
 nan,
 'Victoria Manalo Draves Park',
 'Marietta Green Space',
 'Aptos Playground',
 'Terrace Green Park',
 nan,
 'Mission Bay Commons',
 'Rochambeau Playground',
 'Mission Creek Park',
 'Allyne Park',
 'Cayuga Park',
 '10th Avenue & Clement Mini Park',
 'Parque Niños Unidos',
 '24th & York Mini Park',
 'Adam Rodgers Park',
 'Alice Chalmers Playground',
 'Little Marina Green',
 'Alioto Mini Park',
 'Angelo Rossi Park',
 'Helen Wills Park',
 nan,
 'Broadway Tunnel West Mini Park',
 'Fort Mason',
 'Bayview Playground',
 'Crocker Amazon Playground',
 'Bayview Hill Park',
 nan,
 'Koret Quad',
 'Edgehill Mountain Open Space',
 'Douglass Playground',
 'Dorothy W. Erskine Park',
 'Noe Valley Courts',
 'Duncan-Castro Open Space',
 'Fulton Playground',
 'Richmond Playground',
 'Richmond Recreation Center',
 'George Christopher Playground',
 '29th & Diamond Open Space',
 'Walter Haas Playground',
 'Billy Goat Hill',
 nan,
 'Topaz Open Space',
 nan,
 'Fairmount Open Space',
 'Argonne Playground',
 'Sunset Playground',
 'West Portal Playground',
 'West Sunset Playground',
 'Fallen Bridge Park',
 'Youngblood-Coleman Playground',
 'Presidio Tunnel Tops',
 nan,
 'George Sterling Park',
 'Presidio Heights Playground',
 'Laurel Hill Playground',
 'Sigmund Stern Recreation Grove',
 'Pine Lake Park',
 'Parkside Square',
 'Robert Pender Park',
 'Kelloch-Velasco Park',
 'Rolph Nicol Jr Playground',
 'Michelangelo Playground',
 'Ina Coolbrith Park',
 'Noe & Beaver Mini Park Community Garden',
 'Potrero Hill Recreation Center',
 'Golden Gate Heights Park',
 'Islais Landing',
 'Page & Laguna Mini Park',
 'Seward Mini Park',
 'Mission Playground',
 'Rooftop Park',
 'Koshland Park',
 'Community Park',
 nan,
 'Golden Gate Park',
 'Sutro Heights Park',
 'Fay Park',
 nan,
 'Woh Hei Yuen Recreation Center',
 'Muriel Leff Mini Park',
 'Cabrillo Playground',
 'Merced Heights Playground',
 'Ocean View Park',
 'Langton Community Garden',
 'Jane Warner Plaza',
 'San Jose/Guerrero Park',
 'Naples Green',
 'Naples Green',
 'Brooks Park',
 'Cayuga & Lamartine mini park',
 'Brannan Street Wharf',
 'Pier 94 Wetlands',
 'Little Hollywood Park',
 'Sunnyside Conservatory',
 nan,
 'Pink Triangle Memorial',
 'Baden-Joost Mini Park',
 'Coso Square',
 'Pioneer Park',
 'Corona Heights Park',
 'Harvey Milk Plaza',
 'Sunnyside Playground',
 'India Basin Open Space',
 'The Parks at 5M',
 'Noe Valley Town Square',
 'Agua Vista Park',
 'Coleridge Mini Park',
 'Coleridge Park',
 'Argonne Community Garden',
 'Empire Park',
 'Midtown Terrace Park and Sutro Recreation Center',
 'Transamerica Redwood Park',
 'Woods Yard Park',
 'Hippie Hill',
 'Green Hairstreak Corridor - Quintara Steps',
 'Green Hairstreak Corridor - 14th Avenue & Pacheco',
 'Green Hairstreak Corridor - 12th and Pacheco',
 'Green Hairstreak Corridor - Aerial Steps (access point)',
 'Green Hairstreak Corridor - Aloha & Lomita',
 'Green Hairstreak Corridor - Mount Steps (access point)',
 'Civic Center Plaza',
 'Rocky Outcrop',
 'Starr King Open Space',
 'McCoppin Hub',
 'Palou Community Garden',
 'Palou Phelps Mini Park',
 'Mariposa Park',
 'J.P. Murphy Playground',
 'Benches Park',
 'Mission Bay Kids Park',
 'Bernal Recreation Center',
 'Progress Park',
 nan,
 "Greenie's Conservation Corner",
 'Randolph & Bright Mini Park',
 'Lessing & Sears Mini Park',
 'Yik Oi Huang Peace and Friendship Park',
 'Visitacion Valley Greenway',
 'Hayes Valley Playground',
 'Lakeview and Ashton Mini Park',
 nan,
 'La Playa Park',
 nan,
 'Mountain Lake Park',
 'Miraloma Playground',
 'Grand View Park',
 'Larsen Park',
 nan,
 'Lake Merced Park',
 nan,
 'Emerald Park',
 'Hilltop Park',
 'Mansell Parkway',
 'Shoreview Park',
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 'In Chan Kaajal Park',
 'Tara Street Park',
 'Athens Avalon Greens Terace',
 '50 Beale Street Plaza',
 'Bayview Gateway',
 'Parklab',
 'Jack Early Park',
 nan,
 'Mission Valencia Plaza',
 'Mullen & Peralta Mini Park',
 'Bosworth Street Open Space',
 "Adah's Stairway Garden",
 nan,
 'Tunnel Top Park',
 'Daggett Park',
 nan,
 'Fillmore & Turk Mini Park',
 'Raymond Kimbell Playground',
 nan,
 'Japan Town Peace Plaza',
 'Golden Gate & Steiner Mini Park',
 'Mary Ellen Pleasant Memorial Park',
 nan,
 'Coleman Bluff',
 'Redwood Grove',
 nan,
 'Mission Creek Park',
 "Tenderloin Children's Playground",
 'Rossi Playground Edward St Annex',
 'UCSF Mission Bay Park',
 'Waterfront Plaza',
 'La Playa Park',
 'Margaret S. Hayward Playground',
 'Jefferson Square',
 'Eureka Valley Recreation Center',
 'Gilman Playground',
 nan,
 'Alcatraz Island',
 'Prentiss Mini-Park',
 nan,
 'Alamo Square',
 'Dogpatch Arts Plaza',
 'Francisco Park',
 nan,
 nan,
 'Frank Cresci Plaza',
 'Molinari Mana Park',
 '15th Avenue Steps',
 'Crane Cove Park',
 'Hunters Point Community Youth Park',
 nan,
 nan,
 nan,
 'PG&E Plaza',
 nan,
 nan,
 nan,
 nan,
 'War Memorial Court',
 nan,
 nan,
 'Deepistan National Parklet',
 nan,
 nan,
 'Treat Plaza',
 'Yosemite Slough',
 'The Parks at 5M',
 'Grandview Open Space',
 nan,
 'Pier 29 Public Shore',
 'The Commons',
 nan,
 'moscone dog play area',
 'Buckeye Grove',
 'Panorama Park',
 'Clipper Cove Beach',
 'Rincon Place',
 'Ecker Square',
 'Urban Alchemy Oasis',
 'Urban Park',
 'Mandalay Lane Park',
 'Sunset Reservoir Park',
 "Al's Park",
 'Bayfront Park']

Define thumbnail helper¶

This helper generates a park map thumbnail given a row in parks dataset.

We'll use it to

In [112]:
def generate_park_map(row, zoom=15):
    # Map to longitude and latitude
    longitude = row.geometry.centroid.x
    latitude = row.geometry.centroid.y
    
    # Create figure with an appropriate aspect ratio
    m = folium.Map(
        location=[latitude, longitude],
        zoom_start=zoom,
        tiles='OpenStreetMap',
    )
   
    folium.Marker(
        [latitude, longitude],
        popup=folium.Popup(row['name'], max_width=300, auto_open=True)
    ).add_to(m)
        
    return m
In [174]:
generate_park_map(parks.iloc[0])
Out[174]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Investigate NaN name parks¶

Now that we know the data is reasonable, let's look at anomalies. There's a few parks with NaN for name, so let's see if they're valid parks.

In [114]:
no_name_parks = parks.query('name.isna()')
no_name_parks
Out[114]:
geometry ele gnis:feature_id leisure name wikidata wikipedia historic opening_hours smoking ... leaf_type acres communication:amateur_radio:pota name:pt tourism fee location type disused:landuse source:operator
element id
way 30029902 POLYGON ((-122.41934 37.80672, -122.41897 37.8... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
32862942 POLYGON ((-122.39404 37.79096, -122.394 37.790... NaN NaN park NaN NaN NaN NaN Mo-Fr 08:00-20:00 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
33883156 POLYGON ((-122.41934 37.79765, -122.41932 37.7... NaN NaN park NaN NaN NaN NaN 05:00-24:00 no ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
41373180 POLYGON ((-122.46506 37.73889, -122.46472 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
48537425 POLYGON ((-122.47418 37.72429, -122.47418 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
69422745 POLYGON ((-122.44674 37.80187, -122.44723 37.8... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
84812337 POLYGON ((-122.38706 37.77128, -122.3867 37.77... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
85891398 POLYGON ((-122.43321 37.74195, -122.43334 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
85930055 POLYGON ((-122.46371 37.75846, -122.46318 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
91913157 POLYGON ((-122.40898 37.80847, -122.40896 37.8... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
157018893 POLYGON ((-122.44365 37.7608, -122.44354 37.76... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
161843752 POLYGON ((-122.4358 37.8066, -122.43559 37.806... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
219036273 POLYGON ((-122.44008 37.76212, -122.44007 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
382113061 POLYGON ((-122.44536 37.76337, -122.4454 37.76... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
399402796 POLYGON ((-122.47126 37.77316, -122.47141 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
401354282 POLYGON ((-122.47284 37.78631, -122.47314 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
404847042 POLYGON ((-122.49831 37.7315, -122.49831 37.73... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
407324072 POLYGON ((-122.41913 37.77138, -122.41912 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135696 POLYGON ((-122.49368 37.73306, -122.49356 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135697 POLYGON ((-122.49437 37.73479, -122.49433 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135698 POLYGON ((-122.49321 37.73205, -122.49356 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135699 POLYGON ((-122.49398 37.73304, -122.49396 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135700 POLYGON ((-122.49348 37.73413, -122.49352 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135702 POLYGON ((-122.4934 37.72975, -122.49337 37.72... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135703 POLYGON ((-122.49428 37.732, -122.49423 37.731... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135705 POLYGON ((-122.49393 37.74235, -122.49549 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135706 POLYGON ((-122.49425 37.74037, -122.49413 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135707 POLYGON ((-122.49453 37.74213, -122.49499 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135708 POLYGON ((-122.49427 37.73181, -122.49416 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135709 POLYGON ((-122.49389 37.73511, -122.49399 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
414135710 POLYGON ((-122.49441 37.74036, -122.49428 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
458217887 POLYGON ((-122.42382 37.77434, -122.42374 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
488800989 POLYGON ((-122.41066 37.72666, -122.41039 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
545347966 POLYGON ((-122.4327 37.78347, -122.43263 37.78... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
545436378 POLYGON ((-122.42865 37.77927, -122.42866 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
565996156 POLYGON ((-122.36844 37.72777, -122.36833 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
574610487 POLYGON ((-122.40211 37.77003, -122.40201 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
693102678 POLYGON ((-122.47051 37.71211, -122.47089 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
730336617 POLYGON ((-122.40881 37.80823, -122.40883 37.8... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
775796578 POLYGON ((-122.37648 37.82303, -122.37602 37.8... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
817076988 POLYGON ((-122.38945 37.77214, -122.38945 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
894478070 POLYGON ((-122.44733 37.75461, -122.44821 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
894478071 POLYGON ((-122.44733 37.75461, -122.44741 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
894529444 POLYGON ((-122.38257 37.73112, -122.38243 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
908050668 POLYGON ((-122.43004 37.77972, -122.42996 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
918133828 POLYGON ((-122.39705 37.76157, -122.39694 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
918165494 POLYGON ((-122.3695 37.72682, -122.36947 37.72... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
918165497 POLYGON ((-122.37194 37.72697, -122.37189 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
956484465 POLYGON ((-122.37104 37.72715, -122.37093 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
956484476 POLYGON ((-122.37044 37.72678, -122.37029 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1047715315 POLYGON ((-122.38854 37.77019, -122.38852 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN no roof NaN NaN NaN
1047715319 POLYGON ((-122.38838 37.7702, -122.38836 37.76... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1191526718 POLYGON ((-122.38662 37.75431, -122.38662 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1195049111 POLYGON ((-122.41337 37.73753, -122.41335 37.7... NaN NaN park NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

54 rows × 98 columns

In [175]:
generate_park_map(no_name_parks.iloc[1])
Out[175]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Disregard no-name parks and otherwise clean data¶

Looks like they are kinda valid parks. But small enough where they're unnamed. Let's just disregard them - they're probably not interesting to visit.

Also change / in park names to -. / Causes issues with filenames.

In [168]:
named_parks = parks.query('not name.isna()')
named_parks = named_parks.copy()
named_parks['name'] = named_parks['name'].str.replace('/', '-')
named_parks
Out[168]:
geometry ele gnis:feature_id leisure name wikidata wikipedia historic opening_hours smoking ... leaf_type acres communication:amateur_radio:pota name:pt tourism fee location type disused:landuse source:operator
element id
node 358767175 POINT (-122.49088 37.72237) 16 224922 park Harding Park Q49497924 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803650 POINT (-122.40303 37.79687) 7 1655668 park Jackson Square Historic District Q49506269 NaN district NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803668 POINT (-122.49942 37.72549) 8 1655678 park Lake Merced Sports Center NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803681 POINT (-122.41367 37.72248) 55 1655685 park Louis Sutter Playground Q49519583 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
358803706 POINT (-122.37692 37.72965) 56 1655701 park Milton Myer Recreation Center Q49526782 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
way 1286999777 POLYGON ((-122.39559 37.79113, -122.3952 37.79... NaN NaN park Urban Park NaN NaN NaN Mo-Fr 08:00-20:00 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1293746220 POLYGON ((-122.47178 37.75073, -122.47106 37.7... NaN NaN park Mandalay Lane Park NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1293746848 POLYGON ((-122.48591 37.75188, -122.4818 37.75... NaN NaN park Sunset Reservoir Park NaN NaN NaN 24/7 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1300623937 POLYGON ((-122.44574 37.75953, -122.44508 37.7... NaN NaN park Al's Park NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1329130170 POLYGON ((-122.38623 37.7696, -122.38616 37.76... NaN NaN park Bayfront Park NaN NaN NaN sunrise-sunset NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

286 rows × 98 columns

Sort by size¶

In [169]:
# Project to web mercator
sized_parks = named_parks.copy().to_crs(3857)

# Calculate area in square meters
sized_parks['area'] = sized_parks.geometry.area

# Convert to acres
sized_parks['area_acres'] = (sized_parks.geometry.area / 4046.86).round(2)

# Maintain descending order
sized_parks.sort_values('area_acres', ascending=False, inplace=True)

sized_parks[['name', 'area_acres']]
Out[169]:
name area_acres
element id
relation 8346137 Presidio of San Francisco 2411.04
way 158602261 Golden Gate Park 1611.13
404847043 Lake Merced Park 973.44
28716696 John McLaren Park 571.30
40060675 Candlestick Point State Recreation Area 250.48
... ... ... ...
node 12440345641 Maritime Plaza 0.00
358803668 Lake Merced Sports Center 0.00
358803681 Louis Sutter Playground 0.00
358803650 Jackson Square Historic District 0.00
358767175 Harding Park 0.00

286 rows × 2 columns

Park size distribution¶

Just to get a sense of how many big parks there are. We also want to know how many parks are represented as a point (that is, without geometry).

In [170]:
import matplotlib.pyplot as plt
import numpy as np

def plot_park_size_distribution(sized_parks):
    """
    Create a histogram of park sizes with log scaling.
    Input: GeoDataFrame with 'area_acres' column
    """
    plt.figure(figsize=(12, 6))
    
    # Create histogram with log scale on x-axis due to likely long tail distribution
    plt.hist(sized_parks['area_acres'], 
            bins=np.logspace(np.log10(0.1), np.log10(sized_parks['area_acres'].max()), 20),
            alpha=0.7)
    
    #plt.xscale('log')  # Log scale for x-axis since park sizes likely vary by orders of magnitude
    plt.xlabel('Park Size (acres)')
    plt.ylabel('Number of Parks')
    plt.title('Distribution of San Francisco Park Sizes')
    plt.grid(True, alpha=0.3)
    
    # Add some summary statistics
    plt.figtext(0.15, 0.85, 
                f"Total Parks: {len(sized_parks)}\n"
                f"Median Size: {sized_parks['area_acres'].median():.1f} acres\n"
                f"Mean Size: {sized_parks['area_acres'].mean():.1f} acres",
                bbox=dict(facecolor='white', alpha=0.8))
    
    return plt

plot_park_size_distribution(sized_parks)
Out[170]:
<module 'matplotlib.pyplot' from '/nix/store/1zyma6bfryj88cfdxs59phs5xzgmy5w9-python3-3.12.8-env/lib/python3.12/site-packages/matplotlib/pyplot.py'>
No description has been provided for this image

Export data as HTML and JSON¶

We want to build a standalone webapp to track park visitation progress. So export this data into something a webapp can work with.

In [172]:
import os
import json
from pathlib import Path

def generate_park_maps_and_data(sized_parks, named_parks):
    # Create maps directory if it doesn't exist
    Path("maps").mkdir(exist_ok=True)
    
    # Create dictionary for park sizes
    park_sizes = {}
    
    for idx, park in sized_parks.iterrows():
        name = str(park['name'])
        print(f"Generating map for: {name}")
        
        m = generate_park_map(named_parks[named_parks['name'] == name].iloc[0])
        m.save(f"maps/{name}.html")
        
        # Add to sizes dictionary
        park_sizes[name] = round(park.area_acres, 2)
    
    # Write JSON file
    with open('park_sizes.json', 'w') as f:
        json.dump(park_sizes, f, indent=2, sort_keys=True)
    
    print(f"\nGenerated {len(park_sizes)} maps")
    print("Park sizes saved to park_sizes.json")

generate_park_maps_and_data(sized_parks, named_parks)
Generating map for: Presidio of San Francisco
Generating map for: Golden Gate Park
Generating map for: Lake Merced Park
Generating map for: John McLaren Park
Generating map for: Candlestick Point State Recreation Area
Generating map for: Lands End
Generating map for: Lincoln Park
Generating map for: Glen Canyon Park
Generating map for: Fort Mason
Generating map for: Bayview Hill Park
Generating map for: Crocker Amazon Playground
Generating map for: Mount Davidson Park
Generating map for: Buena Vista Park
Generating map for: Sunset Reservoir Park
Generating map for: Sigmund Stern Recreation Grove
Generating map for: Bernal Heights Park
Generating map for: Pine Lake Park
Generating map for: Sutro Heights Park
Generating map for: Balboa Park
Generating map for: Panhandle
Generating map for: Heron's Head Park
Generating map for: Alcatraz Island
Generating map for: West Sunset Playground
Generating map for: Mission Dolores Park
Generating map for: Corona Heights Park
Generating map for: Presidio Tunnel Tops
Generating map for: Yosemite Slough
Generating map for: Mountain Lake Park
Generating map for: Alamo Square
Generating map for: Moscone Recreation Center
Generating map for: Alta Plaza Park
Generating map for: Lafayette Park
Generating map for: Ocean View Park
Generating map for: Potrero Hill Recreation Center
Generating map for: Pier 94 Wetlands
Generating map for: Saint Mary's Park
Generating map for: Mission Creek Park
Generating map for: Aquatic Park Historic District
Generating map for: Music Concourse
Generating map for: Parkside Square
Generating map for: Holly Park
Generating map for: India Basin Shoreline Park
Generating map for: Marina Green
Generating map for: Larsen Park
Generating map for: McCoppin Square
Generating map for: Mission Creek Park
Generating map for: Golden Gate Heights Park
Generating map for: George Christopher Playground
Generating map for: Crane Cove Park
Generating map for: Angelo Rossi Park
Generating map for: Youngblood-Coleman Playground
Generating map for: Raymond Kimbell Playground
Generating map for: Pioneer Park
Generating map for: Jefferson Square
Generating map for: China Beach
Generating map for: Bayfront Park
Generating map for: Civic Center Plaza
Generating map for: India Basin Open Space
Generating map for: Silver Terrace Playground
Generating map for: Palega Recreation Center
Generating map for: Margaret S. Hayward Playground
Generating map for: China Basin Park
Generating map for: Aptos Playground
Generating map for: Franklin Square
Generating map for: Gilman Playground
Generating map for: Walter Haas Playground
Generating map for: Francisco Park
Generating map for: Jackson Park
Generating map for: Salesforce Park
Generating map for: Sue Bierman Park
Generating map for: Potrero Del Sol Park
Generating map for: Grand View Park
Generating map for: Brooks Park
Generating map for: Duboce Park
Generating map for: Yerba Buena Gardens
Generating map for: Embarcadero Plaza
Generating map for: Parklab
Generating map for: Hilltop Park
Generating map for: Bayview Playground
Generating map for: Sunset Playground
Generating map for: Mansell Parkway
Generating map for: The Crossing at East Cut
Generating map for: Billy Goat Hill
Generating map for: Cayuga Park
Generating map for: Palou Phelps Mini Park
Generating map for: Rincon Park
Generating map for: Koret Quad
Generating map for: Robert Pender Park
Generating map for: Garfield Square
Generating map for: Rolph Playground
Generating map for: Douglass Playground
Generating map for: Coleman Bluff
Generating map for: Tank Hill
Generating map for: Adam Rodgers Park
Generating map for: George Sterling Park
Generating map for: Starr King Open Space
Generating map for: Edgehill Mountain Open Space
Generating map for: Kite Hill Open Space
Generating map for: Joe DiMaggio Playground
Generating map for: Clipper Cove Beach
Generating map for: Buckeye Grove
Generating map for: Victoria Manalo Draves Park
Generating map for: McKinley Square
Generating map for: Mission Bay Commons
Generating map for: Rolph Nicol Jr Playground
Generating map for: Panorama Park
Generating map for: Union Square
Generating map for: Little Marina Green
Generating map for: Miraloma Playground
Generating map for: Washington Square Park
Generating map for: Mariposa Park
Generating map for: Bosworth Street Open Space
Generating map for: Hunters Point Community Youth Park
Generating map for: Dorothy W. Erskine Park
Generating map for: Precita Park
Generating map for: Sunnyside Playground
Generating map for: Esprit Park
Generating map for: Mission Playground
Generating map for: Yik Oi Huang Peace and Friendship Park
Generating map for: Levi's Plaza
Generating map for: Sydney G. Walton Square
Generating map for: Eureka Valley Recreation Center
Generating map for: Warm Water Cove Park
Generating map for: Terrace Green Park
Generating map for: Rocky Outcrop
Generating map for: Alice Chalmers Playground
Generating map for: Brannan Street Wharf
Generating map for: Brotherhood-Head Mini Park
Generating map for: Excelsior Playground
Generating map for: Mission Creek Park
Generating map for: Kelloch-Velasco Park
Generating map for: Grattan Playground
Generating map for: Midtown Terrace Park and Sutro Recreation Center
Generating map for: Laurel Hill Playground
Generating map for: Tulare Park
Generating map for: Little Hollywood Park
Generating map for: Saint Mary's Square
Generating map for: Mission Bay Kids Park
Generating map for: J.P. Murphy Playground
Generating map for: Bayview Gateway
Generating map for: West Portal Playground
Generating map for: Hippie Hill
Generating map for: Huntington Park
Generating map for: Merced Heights Playground
Generating map for: South Beach Park
Generating map for: 29th & Diamond Open Space
Generating map for: Topaz Open Space
Generating map for: Cabrillo Playground
Generating map for: Noe Valley Courts
Generating map for: Shoreview Park
Generating map for: South Park
Generating map for: Koshland Park
Generating map for: Fulton Playground
Generating map for: Boeddeker Park
Generating map for: 10th Avenue & Clement Mini Park
Generating map for: Richmond Recreation Center
Generating map for: Ina Coolbrith Park
Generating map for: Argonne Playground
Generating map for: Richmond Playground
Generating map for: Rochambeau Playground
Generating map for: Helen Wills Park
Generating map for: Allyne Park
Generating map for: Transamerica Redwood Park
Generating map for: Sunset Tunnel Park
Generating map for: Grandview Open Space
Generating map for: In Chan Kaajal Park
Generating map for: Bernal Recreation Center
Generating map for: Fairmount Open Space
Generating map for: Duncan-Castro Open Space
Generating map for: Japan Town Peace Plaza
Generating map for: Daggett Park
Generating map for: Hayes Valley Playground
Generating map for: Tunnel Top Park
Generating map for: Agua Vista Park
Generating map for: UCSF Mission Bay Park
Generating map for: Parque Niños Unidos
Generating map for: Visitacion Valley Greenway
Generating map for: Islais Landing
Generating map for: Progress Park
Generating map for: Seward Mini Park
Generating map for: Lakeview and Ashton Mini Park
Generating map for: 50 Beale Street Plaza
Generating map for: Willie "Woo Woo" Wong Park
Generating map for: Patricia's Green
Generating map for: Mullen & Peralta Mini Park
Generating map for: Waterfront Plaza
Generating map for: War Memorial Court
Generating map for: Pier 29 Public Shore
Generating map for: Emerald Park
Generating map for: Presidio Heights Playground
Generating map for: Michelangelo Playground
Generating map for: Tenderloin Children's Playground
Generating map for: Rooftop Park
Generating map for: The Parks at 5M
Generating map for: Argonne Community Garden
Generating map for: Sunnyside Conservatory
Generating map for: Palou Community Garden
Generating map for: Fillmore & Turk Mini Park
Generating map for: Rossi Playground Edward St Annex
Generating map for: Rincon Place
Generating map for: Woh Hei Yuen Recreation Center
Generating map for: Harvey Milk Plaza
Generating map for: Minnesota Grove
Generating map for: Redwood Grove
Generating map for: The Parks at 5M
Generating map for: Kid Power Park
Generating map for: Fay Park
Generating map for: Woods Yard Park
Generating map for: moscone dog play area
Generating map for: Fallen Bridge Park
Generating map for: Noe Valley Town Square
Generating map for: The Commons
Generating map for: Jane Warner Plaza
Generating map for: Juri Commons
Generating map for: Langton Community Garden
Generating map for: Muriel Leff Mini Park
Generating map for: 15th Avenue Steps
Generating map for: Sergeant John Macaulay Park
Generating map for: Lessing & Sears Mini Park
Generating map for: Alioto Mini Park
Generating map for: Dogpatch Arts Plaza
Generating map for: Adah's Stairway Garden
Generating map for: Coleridge Park
Generating map for: Benches Park
Generating map for: Coso Square
Generating map for: Page & Laguna Mini Park
Generating map for: Al's Park
Generating map for: Broadway Tunnel West Mini Park
Generating map for: San Jose-Guerrero Park
Generating map for: Cottage Row Mini Park
Generating map for: Athens Avalon Greens Terace
Generating map for: La Playa Park
Generating map for: Cayuga & Lamartine mini park
Generating map for: Naples Green
Generating map for: McCoppin Hub
Generating map for: 24th & York Mini Park
Generating map for: Marietta Green Space
Generating map for: Turk-Hyde Mini Park
Generating map for: Urban Park
Generating map for: Greenie's Conservation Corner
Generating map for: Urban Alchemy Oasis
Generating map for: Community Park
Generating map for: Mission Valencia Plaza
Generating map for: Baden-Joost Mini Park
Generating map for: Jack Early Park
Generating map for: La Playa Park
Generating map for: Baker & Broderick Mini Park
Generating map for: Frank Cresci Plaza
Generating map for: Randolph & Bright Mini Park
Generating map for: Golden Gate & Steiner Mini Park
Generating map for: Marini Plaza
Generating map for: Pink Triangle Memorial
Generating map for: Ecker Square
Generating map for: Mandalay Lane Park
Generating map for: Green Hairstreak Corridor - 12th and Pacheco
Generating map for: Noe & Beaver Mini Park Community Garden
Generating map for: Green Hairstreak Corridor - 14th Avenue & Pacheco
Generating map for: Treat Plaza
Generating map for: Mary Ellen Pleasant Memorial Park
Generating map for: Green Hairstreak Corridor - Mount Steps (access point)
Generating map for: Coleridge Mini Park
Generating map for: Tara Street Park
Generating map for: Prentiss Mini-Park
Generating map for: Empire Park
Generating map for: Green Hairstreak Corridor - Quintara Steps
Generating map for: Molinari Mana Park
Generating map for: Naples Green
Generating map for: Green Hairstreak Corridor - Aloha & Lomita
Generating map for: PG&E Plaza
Generating map for: Green Hairstreak Corridor - Aerial Steps (access point)
Generating map for: Deepistan National Parklet
Generating map for: Fairy Circle
Generating map for: Annie St Plaza
Generating map for: Secret Garden
Generating map for: Bush Street-Cottage Row Historic District
Generating map for: Russian Hill-Vallejo Street Crest Historic District
Generating map for: Ulrich Field
Generating map for: Benedetti Diamond
Generating map for: Farallon Islands State Game Refuge
Generating map for: Rolph-Nicol Playground
Generating map for: Milton Myer Recreation Center
Generating map for: Maritime Plaza
Generating map for: Lake Merced Sports Center
Generating map for: Louis Sutter Playground
Generating map for: Jackson Square Historic District
Generating map for: Harding Park

Generated 281 maps
Park sizes saved to park_sizes.json

Tarball the maps up for easier download¶

In [178]:
import tarfile

def archive_maps_tar():
    with tarfile.open("maps.tar.gz", "w:gz") as tar:
        tar.add("maps")
    print("Created maps.tar.gz")

archive_maps_tar()
Created maps.tar.gz