SciCloj logo
This is part of the Scicloj Clojure Data Scrapbook.

Seattle Parks and Neighborhoods - DRAFT

Timothy Prately and Daniel Slutsky

(Probably, this notebook will be divided into a few book chapters.)

Choosing where to live depends on many factors such as job opportunities and cost of living. I like walking, so one factor that is important to me is access to parks. In this analysis we’ll rank neighborhoods by park area proportional to total area. This article demonstrates how to prepare the geospatial data, calculate the value we want, and how to explore the meaning behind the numbers.

(ns index
  (:require [geo
             [geohash :as geohash]
             [jts :as jts]
             [spatial :as spatial]
             [io :as geoio]
             [crs :as crs]]
            [tech.v3.datatype.functional :as fun]
            [tablecloth.api :as tc]
            [scicloj.kindly.v4.kind :as kind]
            [scicloj.kindly.v4.api :as kindly]
            [hiccup.core :as hiccup]
            [charred.api :as charred]
            [clojure2d.color :as color]
            [clojure.string :as str])
  (:import (org.locationtech.jts.index.strtree STRtree)
           (org.locationtech.jts.geom Geometry Point Polygon Coordinate)
           (org.locationtech.jts.geom.prep PreparedGeometry
                                           PreparedLineString
                                           PreparedPolygon
                                           PreparedGeometryFactory)
           (java.util TreeMap)))

Gathering geospatial data

Both the neighborhood geometry and park geometry can be downloaded from Seattle GeoData:

I’ve saved a snapshot in the data directory.

The data format is gzipped GeoJSON. Java has a built-in class for handling gzip streams, and we’ll use the factual/geojson library to parse the string representation.

(defn slurp-gzip
  "Read a gzipped file into a string"
  [path]
  (with-open [in (java.util.zip.GZIPInputStream. (clojure.java.io/input-stream path))]
    (slurp in)))

Now we can conveniently load the data files we downloaded previously.

(defonce neighborhoods-geojson
  (slurp-gzip "data/Seattle/Neighborhood_Map_Atlas_Neighborhoods.geojson.gz"))
(def neighborhoods-features
  (geoio/read-geojson neighborhoods-geojson))

Let’s check that we got some data.

(count neighborhoods-features)
94

This seems like a reasonable number of neighborhoods.

Each member of the dataset is called a Feature. Here is one:

(-> neighborhoods-features
    first
    kind/pprint)
{:properties
 {:OBJECTID 27,
  :L_HOOD "Ballard",
  :S_HOOD "Loyal Heights",
  :S_HOOD_ALT_NAMES nil,
  :Shape__Area 2.13206555455933E7,
  :Shape__Length 18831.00959637},
 :geometry
 #object[org.locationtech.jts.geom.Polygon 0x734a2288 "POLYGON ((-122.376336564723 47.6759176989664, -122.376707907517 47.6759982290459, -122.377903057631 47.6759978849021, -122.379988625303 47.6759893429385, -122.38182788443 47.675992079457, -122.383602752477 47.675979810424, -122.385435721425 47.6759587956618, -122.387087434206 47.6759521343769, -122.387702391216 47.6759476875929, -122.388955759168 47.6759424488678, -122.390449346263 47.6759259868868, -122.391773109273 47.6759158131504, -122.392827172066 47.6759153143353, -122.392956550545 47.6759141859541, -122.392956303464 47.6763287099834, -122.392959618409 47.676929558447, -122.392961263359 47.6775085790216, -122.392971502986 47.6781034200237, -122.392975009807 47.6792517755972, -122.392983771129 47.6798142464259, -122.39300195772 47.6811303942788, -122.393014530791 47.6824285808909, -122.393016158048 47.6837341155494, -122.393022827056 47.685021586284, -122.393030577589 47.6863450742964, -122.393032746621 47.687668638629, -122.393046187318 47.6889956475812, -122.393010665051 47.6902980913372, -122.393002415356 47.6905813205566, -122.392432373275 47.6905826938111, -122.390347910813 47.6905631204492, -122.388192979124 47.6905805029145, -122.385832831602 47.6905766041982, -122.383275316007 47.690593164597, -122.383201215024 47.6905936585447, -122.381453020656 47.6905978829044, -122.379876313408 47.6905988541749, -122.379103841332 47.6906041929746, -122.377117910432 47.6906029639028, -122.376810344766 47.6906051591463, -122.376810264834 47.6905341242701, -122.376810989127 47.6900117143006, -122.376803067488 47.688976146724, -122.376794751014 47.6879443550321, -122.376800402808 47.6870068457338, -122.376784403749 47.6860923366759, -122.376785260609 47.6851813698577, -122.376780535885 47.6842704786057, -122.376787310842 47.6833707854178, -122.376777423242 47.6822860591882, -122.376767820487 47.6811938310584, -122.376770442503 47.680154307228, -122.376770065639 47.6792017979916, -122.376769882216 47.6780678404081, -122.376759750881 47.6775387646826, -122.376761985459 47.676862137338, -122.376772171763 47.6764361697665, -122.376772451106 47.6764114022001, -122.376770700102 47.6763866189683, -122.37676692258 47.6763619488292, -122.376761120573 47.6763374777451, -122.376753802121 47.6763131984825, -122.376744969247 47.6762891966531, -122.376733608705 47.6762655291531, -122.376721246367 47.6762423037704, -122.376706358898 47.6762194979699, -122.376690473449 47.6761972626929, -122.376672575492 47.6761756116819, -122.376653693551 47.6761550023704, -122.376620811506 47.6761243856628, -122.37659791092 47.6761051588887, -122.376573006221 47.6760868163511, -122.376547112434 47.6760693435982, -122.376519722058 47.6760527482053, -122.376336564723 47.6759176989664))"]}

Each feature, in our case, represents a geographic region with a geometry and some properties.

And similarly for the parks:

(defonce parks-geojson
  (slurp-gzip "data/Seattle/Park_Boundary_(details).geojson.gz"))
(def parks-features
  (geoio/read-geojson parks-geojson))
(count parks-features)
2809

There are more parks than neighborhoods, which sounds right.

(delay
  (-> parks-features
      first
      kind/pprint))
{:properties
 {:SE_ANNO_CAD_DATA "",
  :NAMEFLAG 9,
  :ADDRESS " ",
  :MAINT "DPR",
  :LEASE "N",
  :PMA_NAME "East Duwamish GS: S Chicago St",
  :SUBPARCEL 9851,
  :PMA 442,
  :REVIEW_DATE "2004-04-08T00:00:00Z",
  :GlobalID "{D4B7025E-1135-4232-88AB-CBF72932E6AE}",
  :OBJECTID 207882,
  :AMWOID "PROPERTY-EDUWSC",
  :SDQL "QL-D1",
  :USE_ nil,
  :PIN "4006000485",
  :GIS_EDT_DT "2024-01-19T14:07:23Z",
  :SHAPE_Area 1.4691943312522366E-6,
  :SHAPE_Length 0.005215887160444538,
  :GIS_CRT_DT "2024-01-19T14:07:23Z",
  :NAME "EAST DUWAMISH GREENBELT",
  :OWNER "DPR",
  :ACQ_DATE "1997-10-21T00:00:00Z"},
 :geometry
 #object[org.locationtech.jts.geom.MultiPolygon 0x1788033d "MULTIPOLYGON (((-122.28235899499998 47.525165833000074, -122.28168484899999 47.525164389000054, -122.28168307199996 47.52516438600003, -122.28145050399996 47.52516388600003, -122.281450582 47.525147437000044, -122.28092621899998 47.525146310000025, -122.28092721899998 47.52433074500004, -122.28129411599997 47.52433142700005, -122.28247185299995 47.52433360800006, -122.28270306299999 47.52433403400005, -122.28270162899997 47.52516656600005, -122.28235899499998 47.525165833000074)))"]}

And the parks are defined as geographic regions.

Drawing a map

Seattle coordinates

(def Seattle-center
  [47.608013 -122.335167])

The map we will create is A choropleth, though for now, we will use a fixed color, which is not so informative.

We will enrich every feature (e.g., neighborhood) with data relevant for its visual representation.

(defn enrich-feature [{:as   feature :keys [geometry]}
                      {:keys [tooltip-keys
                              style]}]
  (-> feature
      (update :properties
              (fn [properties]
                (-> properties
                    (assoc :tooltip (-> properties
                                        (select-keys tooltip-keys)
                                        (->> (map (fn [[k v]]
                                                    [:p [:b k] ":  " v]))
                                             (into [:div]))
                                        hiccup/html)
                           :style style))))))
(def neighborhoods-enriched-features
  (-> neighborhoods-geojson
      (charred/read-json {:key-fn keyword})
      :features
      (->> (mapv (fn [feature]
                   (-> feature
                       (enrich-feature
                        {:tooltip-keys [:L_HOOD :S_HOOD]
                         :style {:opacity     0.3
                                 :fillOpacity 0.1
                                 :color      "purple"
                                 :fillColor  "purple"}})))))))

Here is how we may generate a Choroplet map in Leaflet:

(defn choropleth-map [details]
  (delay
    (kind/reagent
     ['(fn [{:keys [provider
                    center
                    enriched-features]}]
         [:div
          {:style {:height "900px"}
           :ref   (fn [el]
                    (let [m (-> js/L
                                (.map el)
                                (.setView (clj->js center)
                                          11))]
                      (-> js/L
                          .-tileLayer
                          (.provider provider)
                          (.addTo m))
                      (-> js/L
                          (.geoJson (clj->js enriched-features)
                                    (clj->js {:style (fn [feature]
                                                       (-> feature
                                                           .-properties
                                                           .-style))}))
                          (.bindTooltip (fn [layer]
                                          (-> layer
                                              .-feature
                                              .-properties
                                              .-tooltip)))
                          (.addTo m))))}])
      details]
     {:reagent/deps [:leaflet]})))

We pick a tile layer provider from leaflet-providers.

(defn Seattle-choropleth-map [enriched-features]
  (choropleth-map
   {:provider "OpenStreetMap.Mapnik"
    :center     Seattle-center
    :enriched-features enriched-features}))

For our basic neighborhoods map:

(delay
  (Seattle-choropleth-map
   neighborhoods-enriched-features))

Now, let us see the parks:

(def parks-enriched-features
  (-> parks-geojson
      (charred/read-json {:key-fn keyword})
      :features
      (->> (mapv (fn [feature]
                   (-> feature
                       (enrich-feature
                        {:tooltip-keys [:PMA_NAME :NAME]
                         :style {:opacity     0.3
                                 :fillOpacity 0.1
                                 :color      "darkgreen"
                                 :fillColor  "darkgreen"}})))))))

Coordinate conversions

Both datasets use the WGS84 coordinate system.

EPSG:4326

For area computations we need to convert them to a coordinate system which is locally correct in terms of distances in a region around Seattle.

EPSG:2285

United States (USA) - Oregon and Washington. [1 3]:

Center coordinates Projected bounds WGS84 bounds
[1692592.39 -541752.55] [[559165.71 -1834123.81] [2832684.98 777497.1]] [[-124.79 41.98] [-116.47 49.05]]
(def crs-transform
  (geo.crs/create-transform (geo.crs/create-crs 4326)
                            (geo.crs/create-crs 2285)))
(defn wgs84->Seattle
  "Transforming latitude-longitude coordinates
  to local Euclidean coordinates around Seattle."
  [geometry]
  (geo.jts/transform-geom geometry crs-transform))

Some geometrical functions

(defn area [geometry]
  (.getArea geometry))
(defn buffer [geometry radius]
  (.buffer geometry radius))
(defn intersection [geometry1 geometry2]
  (.intersection geometry1 geometry2))

Geometry datasets

(defn geojson->dataset [geojson dataset-name]
  (-> geojson
      (->> (map (fn [{:keys [geometry properties]}]
                  (assoc properties :geometry geometry))))
      tc/dataset
      (tc/map-columns :geometry [:geometry] wgs84->Seattle)
      (tc/set-dataset-name dataset-name)))
(def neighborhoods
  (-> neighborhoods-features
      (geojson->dataset "Seattle neighborhoods")
      (tc/add-column :feature neighborhoods-enriched-features)))
(delay
  (-> neighborhoods
      (tc/drop-columns [:geometry :feature])
      (kind/table {:element/max-height "600px"})))
OBJECTID L_HOOD S_HOOD S_HOOD_ALT_NAMES Shape__Area Shape__Length
27 Ballard Loyal Heights 2.13206555455933E7 18831.00959637
28 Ballard Ballard Adams 2.25521329700012E7 29926.3393002841
29 Ballard Whittier Heights 1.41956874919434E7 15934.4392663199
30 Ballard West Woodland 2.21993668730164E7 21789.6510873493
31 North Central Phinney Ridge Woodland Park 3.21231178777466E7 27120.7859379681
32 North Central Wallingford Meridian, Tangle Town, Northlake 4.20683426137695E7 33040.2469861198
33 North Central Fremont 2.65037565718689E7 25999.2849357187
34 North Central Green Lake 3.73146297898865E7 25387.7074962486
35 Northeast View Ridge 2.56129799440918E7 22657.0394732799
36 Northeast Ravenna University Village 3.67833915366516E7 31163.6208763331
37 Northeast Sand Point 1.92498571397095E7 21396.6958008648
38 Northeast Bryant 1.54850780333252E7 20928.0017243062
39 Northeast Windermere Hawthorne Hills 2.23639666230164E7 33332.8291968304
40 Northeast Laurelhurst 1.90517768183594E7 26489.2422321737
41 Northeast Roosevelt Fairview 2.1491594324707E7 22866.0797374364
42 University District University of Washington 2.55236751180115E7 30983.2126641678
43 Queen Anne East Queen Anne 1.93546995965576E7 21488.397378299
44 Queen Anne West Queen Anne 1.79749859528503E7 20631.7057292923
45 Queen Anne Lower Queen Anne Uptown, Seattle Center 1.75156244566956E7 20496.7289222394
46 Queen Anne North Queen Anne 2.9604288333252E7 26753.5542817429
47 Cascade Westlake 3645184.07894897 11017.3231739615
48 Cascade Eastlake 7426907.96139526 16672.5117837403
49 Cascade South Lake Union 1.6107105419342E7 29323.5462843847
50 Magnolia Lawton Park 5.5091525290863E7 38766.0673349107
51 Magnolia Briarcliff Carleton Park 2.65509365782471E7 26609.7912261135
52 Magnolia Southeast Magnolia 1.84692638882751E7 20223.1801501522
53 Central Area Madrona 1.38454828085938E7 17052.9427067693
54 Central Area Harrison/Denny-Blaine 1.36033956731873E7 17241.2743191595
55 Central Area Minor Central District, Squire Park 1.7933144708252E7 18241.5487859812
56 Central Area Leschi 1.80917413764954E7 20413.0560516882
57 Central Area Mann Central District, Garfield 1.11338288620605E7 17843.105758736
58 Central Area Atlantic Judkins Park, Jackson Place, Coleman 2.06649862726135E7 25426.2311626675
59 Downtown Pike-Market Pike Place Market 2343359.32580566 7326.58173024624
60 Downtown Belltown Denny Regrade 9845864.78594971 17836.7271544608
61 Downtown International District Chinatown, ID, Little Saigon 6169375.81655884 11772.3871410021
62 Downtown Central Business District Commercial Core, West Edge 9477398.61834717 18209.4628624588
63 Downtown First Hill 9517568.47363281 13225.2335159542
64 Downtown Yesler Terrace 5348937.24771118 9611.35354641661
65 Downtown Pioneer Square 7545979.0869751 17297.5867148564
66 Interbay Interbay 3.35039410921631E7 64207.5867611718
67 Greater Duwamish SODO 4.96031675905914E7 38520.9885110863
68 Greater Duwamish Georgetown 5.13050726461182E7 45963.6656769607
69 Greater Duwamish South Park 2.94234521522369E7 30433.4048686311
70 Greater Duwamish Harbor Island 1.78323007354431E7 24381.2966280601
71 West Seattle Seaview 1.8463061797821E7 23122.2640032568
72 West Seattle Gatewood Morgan Junction 2.28217074689484E7 23801.2647005122
73 West Seattle Arbor Heights 2.61973140573883E7 28162.4351386166
74 West Seattle Alki 2.45834691841736E7 45568.1378536906
75 West Seattle North Admiral Belvidere 4.85814163202972E7 30687.7844700837
76 West Seattle Fairmount Park 1.61539000976257E7 24955.7128414259
77 West Seattle Genesee Alaska Junction, West Seattle Junction 2.11649765813446E7 19870.8696089241
78 West Seattle Fauntleroy Endolyne, Arroyo Heights, Brace Point 3.38818638706665E7 42276.5317877774
79 Beacon Hill North Beacon Hill Jefferson Park 4.84759144557953E7 33865.4891739901
80 Beacon Hill Mid-Beacon Hill 5.26204707883301E7 40522.1829275323
81 Beacon Hill South Beacon Hill 3.84488268989563E7 38996.7151070849
82 Beacon Hill Holly Park New Holly 8444235.97859192 15848.3624185113
83 Rainier Valley Brighton 1.8366938275177E7 18911.3293490837
84 Rainier Valley Dunlap 1.96016012150879E7 20847.6531922997
85 Rainier Valley Rainier Beach 3.31282361414948E7 34965.6132100475
86 Rainier Valley Rainier View Lake Ridge 1.82485661794434E7 34791.8218147105
87 Rainier Valley Mount Baker North Rainier 2.89869952343292E7 26318.9819054871
88 Rainier Valley Columbia City Columbia Heights 3.74065764927979E7 35177.0608039675
89 Delridge Highland Park 3.98103334158325E7 31111.0630837714
90 Delridge North Delridge Avalon, Luna Park, Pigeon Point 2.94546565672607E7 23549.9313666304
91 Delridge Riverview 3.30382671929626E7 25917.1176391015
92 Delridge High Point 2.33430083368683E7 23180.3963596714
93 Delridge South Delridge White Center 1.79233162238464E7 23416.3405359794
94 Delridge Roxhill Westwood Village 1.87810598441162E7 22360.0472289145
95 Seward Park Seward Park Lakewood, Hillman City 4.38352790059662E7 52212.7868103531
96 Northeast Wedgwood 3.05997136261597E7 23840.2187274324
97 Capitol Hill Portage Bay Roanoke Park 4421635.26721191 10013.2739563989
98 Capitol Hill Montlake North Capitol Hill 2.1474786741394E7 46165.83098345
99 Capitol Hill Madison Park Broadmoor, Washington Park 2.46809502223511E7 26230.4347480002
100 Capitol Hill Broadway Pike/Pine 3.02392405212402E7 26851.9474418256
101 Capitol Hill Stevens Interlaken Park, Miller Park, Madison-Miller 2.60395920790405E7 25522.3456368768
102 Lake City Victory Heights 2.15127314890137E7 20753.0018992847
103 Lake City Matthews Beach 3.09809783014832E7 31369.8925404597
104 Lake City Meadowbrook 1.70348487789307E7 18770.2820324215
105 Lake City Olympic Hills 2.58367421641541E7 19993.8160570763
106 Lake City Cedar Park 2.04414858487244E7 22788.760382662
110 Northwest Broadview 4.81134497303162E7 34640.309665739
111 Northwest Bitter Lake 2.76903364438171E7 26446.2030540938
112 Northgate Haller Lake 4.72030810796204E7 29413.5534484151
113 Northgate Pinehurst Jackson Park 2.94388508770142E7 26171.2717608103
114 Northwest North Beach/Blue Ridge 3.10622649915771E7 32947.8059119899
115 Northgate Licton Springs North College Park 2.17047062611389E7 20132.8982458333
116 Northgate Maple Leaf Olympic View 3.43804707826233E7 25503.0574082691
117 Northwest Crown Hill 1.58657504196777E7 18997.8080379411
118 Northwest Greenwood 4.20445636731262E7 26501.5265911049
119 Ballard Sunset Hill Golden Gardens, Shilshole 2.43356204689941E7 29416.7300633571
121 University District University District 1.36862548569946E7 21581.6459789299
123 University District University Heights Cowen Park 1.03757480522461E7 15163.9069096811
124 Downtown Denny Triangle Denny Regrade 5128172.31045532 10574.1779826691
126 Greater Duwamish Industrial District 6.24341310114746E7 88995.7569839975
(def parks
  (-> parks-features
      (geojson->dataset "Seattle parks")
      ;; avoiding some [linestring pathologies](https://gis.stackexchange.com/questions/50399/fixing-non-noded-intersection-problem-using-postgis)
      (tc/map-columns :geometry [:geometry] #(buffer % 1))))
(delay
  (-> parks
      (tc/drop-columns [:geometry :feature])
      (tc/head 20)
      (kind/table {:element/max-height "600px"})))
SE_ANNO_CAD_DATA NAMEFLAG ADDRESS MAINT LEASE PMA_NAME SUBPARCEL PMA REVIEW_DATE GlobalID OBJECTID AMWOID SDQL USE_ PIN GIS_EDT_DT SHAPE_Area SHAPE_Length GIS_CRT_DT NAME OWNER ACQ_DATE
9 DPR N East Duwamish GS: S Chicago St 9851 442 2004-04-08T00:00:00Z {D4B7025E-1135-4232-88AB-CBF72932E6AE} 207882 PROPERTY-EDUWSC QL-D1 4006000485 2024-01-19T14:07:23Z 1.4691943312522366E-6 0.005215887160444538 2024-01-19T14:07:23Z EAST DUWAMISH GREENBELT DPR 1997-10-21T00:00:00Z
9 DPR N East Duwamish GS: S Chicago St 4779 443 2004-04-08T00:00:00Z {26B4F4BC-F9AE-42D4-B062-51387C6D9FFF} 207883 PROPERTY-EDUWC QL-D1 0603001220 2024-01-19T14:07:23Z 1.460570191594512E-7 0.0015461198840460832 2024-01-19T14:07:23Z EAST DUWAMISH GREENBELT DPR 1994-10-06T00:00:00Z
9 DPR N East Duwamish GS: S Chicago St 4711 443 2004-04-08T00:00:00Z {E97D7F7F-2666-4008-A905-2F416A66C2A1} 207884 PROPERTY-EDUWC QL-D1 0603001220 2024-01-19T14:07:23Z 9.743577447048599E-8 0.0013271653095071236 2024-01-19T14:07:23Z EAST DUWAMISH GREENBELT DPR 1994-10-06T00:00:00Z
9 DPR N East Duwamish GS: S Chicago St 4779 443 2004-04-08T00:00:00Z {C28A4700-BB4F-4C25-928E-57022F6D001B} 207885 PROPERTY-EDUWC QL-D1 0603001220 2024-01-19T14:07:23Z 4.87386722719263E-8 0.0011082207640129814 2024-01-19T14:07:23Z EAST DUWAMISH GREENBELT DPR 1994-10-06T00:00:00Z
9 DPR N East Duwamish GS: S Chicago St 4712 443 2004-04-08T00:00:00Z {4DB6A932-327A-4E2E-AC8A-C068D114AA61} 207886 PROPERTY-EDUWC QL-D1 0603001220 2024-01-19T14:07:23Z 9.757207624044397E-8 0.0013284113092379031 2024-01-19T14:07:23Z EAST DUWAMISH GREENBELT DPR 1994-10-06T00:00:00Z
9 DPR N Genesee Park and Playfield 4618 409 1899-12-30T00:00:01Z {AD2E47C9-323B-4DDE-8186-98A4FC79C3F8} 207887 PROPERTY-GENPK QL-D1 4154300585 2024-01-19T14:07:23Z 2.892289652506793E-6 0.007000440212562059 2024-01-19T14:07:23Z GENESEE PARK AND PLAYFIELD DPR 1996-06-03T00:00:00Z
9 5244 SW JACOBSEN ROAD DPR N Wolf Creek Ravine Natural Area 16397 278 2004-04-19T00:00:00Z {A7E54352-0DC3-47E4-B562-DAA0F18B78E2} 207888 PROPERTY-WLFCRAV QL-D1 5344200125 2024-01-19T14:07:23Z 6.25557675764001E-8 0.0010504796990982068 2024-01-19T14:07:23Z WOLF CREEK RAVINE NATURAL AREA DPR 2004-04-07T00:00:00Z
9 DPR N Jefferson Park 15550 114 2004-04-08T00:00:00Z {B82B7BD2-DCD9-49A2-BE5D-30C1D9BF4392} 207889 PROPERTY-JEFFPK QL-D1 1624049270 2024-01-19T14:07:23Z 3.2670040661028276E-6 0.018380332716286137 2024-01-19T14:07:23Z JEFFERSON PARK DPR 1988-07-25T00:00:00Z
9 DPR N Queen Anne Boulevard 753 328 2004-04-09T00:00:00Z {3DA31C7B-C33D-4DD9-9092-71B1DA135BC8} 207890 PROPERTY-QABL QL-D1 2533300180 2024-01-19T14:07:23Z 5.790553187521671E-9 4.111515370853996E-4 2024-01-19T14:07:23Z QUEEN ANNE BOULEVARD DPR 1910-07-25T00:00:01Z
9 DPR N Queen Anne Boulevard 4688 328 2004-04-09T00:00:00Z {D3DA12EE-31E0-4476-95CE-1739E8FF8550} 207891 PROPERTY-QABL QL-D1 2533300180 2024-01-19T14:07:23Z 5.139665582905777E-9 3.9228813174494234E-4 2024-01-19T14:07:23Z QUEEN ANNE BOULEVARD DPR 1910-07-25T00:00:01Z
7 DPR N Ravenna Woods 15807 4411 2004-05-05T00:00:00Z {B1A2F3C6-C43A-4600-8064-A3DEFAE61DDC} 207892 PROPERTY-RAVWOOD QL-D1 0925049168 2024-01-19T14:07:23Z 5.585829095854119E-7 0.0030915009702507513 2024-01-19T14:07:23Z RAVENNA WOODS DPR 2002-07-02T00:00:00Z
9 DPR N Montlake Playfield 1507 376 1998-10-15T00:00:00Z {BF38EE1A-DBAB-400C-B083-B3F8B6A1EB39} 207893 PROPERTY-MTLKPF QL-D1 4089400080 2024-01-19T14:07:23Z 3.917576385699785E-7 0.0026768636765498316 2024-01-19T14:07:23Z MONTLAKE PLAYFIELD DPR 1933-12-31T00:00:01Z
9 DPR N Montlake Playfield 1507 376 2004-03-30T00:00:00Z {4CC47610-4927-465F-A346-04F66008D480} 207894 PROPERTY-MTLKPF QL-D1 6788202280 2024-01-19T14:07:23Z 1.1273410584671711E-6 0.004459900867682873 2024-01-19T14:07:23Z MONTLAKE PLAYFIELD DPR 1933-12-31T00:00:01Z
9 DPR N Montlake Playfield 1507 376 2004-03-30T00:00:00Z {10310B09-822A-4344-95CC-2D5D90C2466C} 207895 PROPERTY-MTLKPF QL-D1 6788202280 2024-01-19T14:07:23Z 1.4591960880701082E-6 0.006312257575513224 2024-01-19T14:07:23Z MONTLAKE PLAYFIELD DPR 1933-12-31T00:00:01Z
9 4357 PALATINE AVE N DPR N Fremont Peak Park 16454 4424 2004-10-06T00:00:00Z {A13D75B6-B355-4BDF-84CF-4D2838170201} 207896 PROPERTY-FRMPKPK QL-D1 6610000810 2024-01-19T14:07:23Z 6.118914081332531E-8 0.0011669443524576426 2024-01-19T14:07:23Z FREMONT PEAK PARK DPR 2004-09-30T00:00:00Z
9 DPR N SW Queen Anne Greenbelt 16459 234 2005-01-06T00:00:00Z {A13C70F6-F0AE-4E55-A12C-990BBC545F8D} 207897 PROPERTY-SWQAGRB QL-D1 7705100037 2024-01-19T14:07:23Z 5.565195258199712E-9 3.556012201607765E-4 2024-01-19T14:07:23Z SW QUEEN ANNE GREENBELT DPR 2004-11-04T00:00:00Z
3 9026 4TH AVE S DPR N Marra-Desimone Park 16455 4447 2007-02-21T00:00:00Z {E641A30D-FE4B-4B1D-9358-7F0F71324691} 207898 PROPERTY-MARDESPK QL-D1 3224049044 2024-01-19T14:07:23Z 2.211413981358282E-6 0.006388002898489655 2024-01-19T14:07:23Z MARRA-DESIMONE PARK DPR 2004-12-28T00:00:00Z
9 9026 4TH AVE S DPR N Marra-Desimone Park 16455 4447 2007-02-21T00:00:00Z {6A440787-F078-4DB9-9187-DA0E029A8E18} 207899 PROPERTY-MARDESPK QL-D1 3224049035 2024-01-19T14:07:23Z 1.981420659558925E-6 0.009774073825241834 2024-01-19T14:07:23Z MARRA-DESIMONE PARK DPR 2004-12-28T00:00:00Z
9 DPR Y Meadowbrook Playfield 803 352 {49C14F14-94FF-4080-9DE8-56EDF006145A} 207900 PROPERTY-MBPF QL-D1 2024-01-19T14:07:23Z 5.268695375108406E-7 0.00550990095454217 2024-01-19T14:07:23Z MEADOWBROOK PLAYFIELD SSD1
9 DPR N Meadowbrook Teen Life Center 352 {D099D793-CFEA-44E9-A57B-D8A1BA4525AF} 207901 PROPERTY-MBPF QL-D1 2024-01-19T14:07:23Z 8.504523207167994E-8 0.0011865488770908574 2024-01-19T14:07:23Z MEADOWBROOK TEEN LIFE CENTER SSD1

A Spatial index structure

We need an index structure to quickly match between the two sets of geometries.

See the JTS SearchUsingPreparedGeometryIndex tutorial.

(defn make-spatial-index [dataset & {:keys [geometry-column]
                                     :or   {geometry-column :geometry}}]
  (let [tree (org.locationtech.jts.index.strtree.STRtree.)]
    (doseq [row (tc/rows dataset :as-maps)]
      (let [geometry (row geometry-column)]
        (.insert tree
                 (.getEnvelopeInternal geometry)
                 (assoc row
                        :prepared-geometry
                        (org.locationtech.jts.geom.prep.PreparedGeometryFactory/prepare geometry)))))
    tree))
(def parks-index
  (make-spatial-index parks))
(defn intersecting-places [region spatial-index]
  (->> (.query spatial-index (.getEnvelopeInternal region))
       (filter (fn [row]
                 (.intersects (:prepared-geometry row) region)))
       tc/dataset))

For example, let us find the parks intersecting with the first neighborhood:

(delay
  (-> neighborhoods
      :geometry
      first
      (intersecting-places parks-index)
      (tc/select-columns [:PMA_NAME :NAME])))

_unnamed [2 2]:

:PMA_NAME :NAME
Salmon Bay Park SALMON BAY PARK
Loyal Heights Playfield LOYAL HEIGHTS PLAYFIELD

A Joined dataset

We compute a spatial join of the two datasets.

Note that even though many parks will appear as intersecting many neighbourhoods, this is not too memory-heavy, since they are references to the same map.

(def neighborhoods-with-parks
  (-> neighborhoods
      (tc/map-columns :parks
                      [:geometry]
                      #(intersecting-places % parks-index))))
(delay
  (-> neighborhoods-with-parks
      (tc/map-columns :n-parks
                      [:parks]
                      tc/row-count)
      (tc/select-columns [:L_HOOD :S_HOOD :n-parks])
      (kind/table {:element/max-height "600px"})))
L_HOOD S_HOOD n-parks
Ballard Loyal Heights 2
Ballard Ballard 7
Ballard Whittier Heights 4
Ballard West Woodland 5
North Central Phinney Ridge 11
North Central Wallingford 27
North Central Fremont 15
North Central Green Lake 19
Northeast View Ridge 15
Northeast Ravenna 12
Northeast Sand Point 17
Northeast Bryant 9
Northeast Windermere 5
Northeast Laurelhurst 7
Northeast Roosevelt 22
University District University of Washington 3
Queen Anne East Queen Anne 62
Queen Anne West Queen Anne 46
Queen Anne Lower Queen Anne 6
Queen Anne North Queen Anne 19
Cascade Westlake 3
Cascade Eastlake 18
Cascade South Lake Union 33
Magnolia Lawton Park 83
Magnolia Briarcliff 36
Magnolia Southeast Magnolia 34
Central Area Madrona 30
Central Area Harrison/Denny-Blaine 33
Central Area Minor 14
Central Area Leschi 43
Central Area Mann 11
Central Area Atlantic 71
Downtown Pike-Market 13
Downtown Belltown 15
Downtown International District 8
Downtown Central Business District 8
Downtown First Hill 7
Downtown Yesler Terrace 5
Downtown Pioneer Square 18
Interbay Interbay 35
Greater Duwamish SODO 0
Greater Duwamish Georgetown 4
Greater Duwamish South Park 10
Greater Duwamish Harbor Island 0
West Seattle Seaview 3
West Seattle Gatewood 15
West Seattle Arbor Heights 15
West Seattle Alki 68
West Seattle North Admiral 180
West Seattle Fairmount Park 5
West Seattle Genesee 9
West Seattle Fauntleroy 35
Beacon Hill North Beacon Hill 158
Beacon Hill Mid-Beacon Hill 74
Beacon Hill South Beacon Hill 93
Beacon Hill Holly Park 2
Rainier Valley Brighton 5
Rainier Valley Dunlap 26
Rainier Valley Rainier Beach 76
Rainier Valley Rainier View 9
Rainier Valley Mount Baker 136
Rainier Valley Columbia City 75
Delridge Highland Park 23
Delridge North Delridge 116
Delridge Riverview 121
Delridge High Point 136
Delridge South Delridge 7
Delridge Roxhill 12
Seward Park Seward Park 56
Northeast Wedgwood 12
Capitol Hill Portage Bay 4
Capitol Hill Montlake 54
Capitol Hill Madison Park 29
Capitol Hill Broadway 37
Capitol Hill Stevens 40
Lake City Victory Heights 26
Lake City Matthews Beach 32
Lake City Meadowbrook 19
Lake City Olympic Hills 3
Lake City Cedar Park 11
Northwest Broadview 32
Northwest Bitter Lake 2
Northgate Haller Lake 3
Northgate Pinehurst 8
Northwest North Beach/Blue Ridge 32
Northgate Licton Springs 6
Northgate Maple Leaf 18
Northwest Crown Hill 5
Northwest Greenwood 36
Ballard Sunset Hill 9
University District University District 11
University District University Heights 21
Downtown Denny Triangle 3
Greater Duwamish Industrial District 5

Computing areas

For every neighborhood, we will compute the proportion of its area covered by parks.

TODO: L_HOOD should be used, S_HOOD produces too many rows to be understood (maybe S_HOOD would be interesting for looking at one L_HOOD at a time)

(def neighborhoods-with-park-proportions
  (-> neighborhoods-with-parks
      (tc/map-columns :neighborhood-area
                      [:geometry]
                      area)
      (tc/map-columns :intersection-area
                      [:geometry :parks]
                      (fn [neigh-geometry parks]
                        (->> parks
                             :geometry
                             (map (fn [park-geometry]
                                    (area
                                     (.intersection (.buffer park-geometry 1)
                                                    neigh-geometry))))
                             fun/sum)))
      (tc/map-columns :park-names
                      [:parks]
                      (fn [parks]
                        (->> parks
                             :PMA_NAME
                             distinct
                             vec)))
      (tc/map-columns :park-names-str
                      [:park-names]
                      (partial str/join ","))
      (tc/add-column :park-proportion
                     #(fun// (:intersection-area %)
                             (:neighborhood-area %)))))
(delay
  (-> neighborhoods-with-park-proportions
      (tc/select-columns [:L_HOOD
                          :S_HOOD
                          :park-names
                          :neighborhood-area
                          :intersection-area
                          :park-proportion])
      (tc/order-by [:park-proportion] :desc)
      (kind/table {:element/max-height "600px"})))
L_HOOD S_HOOD park-names neighborhood-area intersection-area park-proportion
Northeast Sand Point
["Warren G. Magnuson Park"]
1.924985714007309E7 1.2694407322392896E7 0.6594546250406457
Magnolia Lawton Park
["Magnolia Manor Park"
 "Lawton Park"
 "Discovery Park"
 "Kiwanis Memorial Preserve Park"
 "Discovery Park Boulevard"
 "Discovery Park Tidelands"
 "Kiwanis Ravine Overlook"
 "Daybreak Star"
 "Commodore Park"]
5.5091525292193405E7 2.5768911594667178E7 0.46774728886148104
Delridge North Delridge
["Greg Davis Park"
 "Cottage Grove Park"
 "Rotary Viewpoint"
 "Camp Long"
 "West Seattle Golf Course"
 "West Seattle Stadium"
 "Longfellow Creek GS: North"
 "Puget Boulevard"
 "West Duwamish Greenbelt"
 "Pigeon Point"
 "Delridge Playfield"
 "Westbridge Shops"
 "WEST DUWAMISH GREENBELT"]
2.945465656812994E7 1.3245569878227614E7 0.44969357723081976
North Central Green Lake
["Ravenna Boulevard"
 "Green Lake Park"
 "Green Lake"
 "Crescent Place"
 "North Park Shops"]
3.731462978987473E7 1.5314645167249074E7 0.41041932489987293
Seward Park Seward Park
["Martha Washington Park"
 "Seward Park"
 "Lake Washington Boulevard"
 "Lakewood Playground"
 "Lakewood Moorage"
 "Genesee Park and Playfield"
 "Stan Sayres Memorial Park"]
4.3835279006813824E7 1.3252664479684925E7 0.30232873566573876
Delridge Riverview
["Delridge and Myrtle"
 "West Duwamish GS: Riverview"
 "Riverview Playfield"
 "West Duwamish GS: Puget Park"
 "Puget Creek Edible Park"
 "Puget Creek Greenspace"
 "Puget Ridge Playground"
 "Delridge Wetland"
 "Puget Park"
 "Puget Boulevard"
 "Pigeon Point"]
3.303826719332341E7 8769575.924383609 0.2654369211638261
North Central Phinney Ridge
["Cascade Place"
 "Sunset Place"
 "Rainier Place"
 "Woodland Park Zoo"
 "Woodland Park"
 "Linden Orchard Park"
 "Green Lake Park"]
3.2123117878649313E7 8349752.958056866 0.25992971758219474
Northgate Pinehurst
["Hubbard Homestead Park"
 "Victory Creek Park"
 "Pinehurst Playground"
 "Flicker Haven Natural Area on Thornton Creek"
 "Licorice Fern Natural Area on Thornton Creek"
 "Jackson Park Golf Course"]
2.9438850877818238E7 7646861.188494857 0.2597540651376668
Capitol Hill Montlake
["Washington Park and Arboretum"
 "Interlaken Park"
 "Montlake Boulevard"
 "Lake Washington Boulevard"
 "East Montlake Park"
 "Grand Army Cemetery"
 "Montlake Playfield"
 "Harvard-Miller/Roanoke Annex"
 "West Montlake Park"]
2.14747867418963E7 5452986.107546446 0.25392504116969533
West Seattle Fauntleroy
["Fauntleroy Park"
 "Arroyos Natural Area"
 "Stim Bullitt Natural Area"
 "Endolyne Park"
 "Fauntleroy Creek Ravine"
 "Lincoln Park"
 "Kilbourne Park"
 "Solstice Park"]
3.3881863871407755E7 7399817.180664994 0.2184005345381709
Beacon Hill North Beacon Hill
["Cheasty GS: Cheasty Blvd"
 "Jefferson Park Golf Course"
 "Cheasty Boulevard"
 "Jefferson Park"
 "East Duwamish GS: Beacon Ave S"
 "Twelfth Avenue South Viewpoint"
 "Stevens Place"
 "Cheasty Greenspace: McClellan"
 "East Duwamish GS: I-90"
 "Beacon Hill Playground"
 "Future Sister City Park"
 "Katie Black's Garden"
 "Daejeon Park"
 "Lewis Park"
 "Dr. Jose Rizal Park"
 "Sturgus Park"]
4.847591445665426E7 1.046069634381901E7 0.2157916247907537
Delridge Highland Park
["West Duwamish GS: Othello St."
 "Westcrest Park"
 "Highland Park Playground"]
3.981033341691431E7 8327022.199101201 0.20916735642217155
Capitol Hill Madison Park
["Lambert Place"
 "Hyde Place"
 "Madison Park"
 "Madison Park North Beach"
 "Washington Park and Arboretum"
 "Lake Washington Boulevard"
 " Lake Washington Boulevard"]
2.4680950222860403E7 4675806.696395554 0.18945002741688
Rainier Valley Mount Baker
["S Charlestown & 35th Ave S"
 "Stan Sayres Memorial Park"
 "Hunter Boulevard"
 "Horton Hil Corridor"
 "Lakewood Triangle"
 "Trudys Triangle"
 "Mount Baker Park"
 "Lake Washington Boulevard"
 "Landing Parkway"
 "Sierra Place"
 "Mount Claire Park"
 "Colman Park"
 "East Portal Viewpoint"
 "South Day Street Park"
 "York Playground"
 "Mount Baker Boulevard"
 "Martin Luther King JR Memorial"
 "College Street Park"
 "Amy Yee Tennis Center"
 "Bradner Gardens Park"
 "Mt Baker Ridge Viewpoint"
 "Sam Smith Park"]
2.8986995235084333E7 4682493.1951638255 0.16153772259555838
Delridge High Point
["Walt Hundley Playfield"
 "Longfellow Creek GS: South"
 "Longfellow Creek GS: Central"
 "Camp Long"]
2.3343008337069765E7 3379054.5025715176 0.14475659922570583
Northwest Broadview
["Carkeek Park"
 "Pipers Creek Natural Area"
 "Llandover Woods Greenspace"]
4.8113449731243916E7 6789015.469879707 0.14110431714629385
Central Area Leschi
["Lake Washington Boulevard"
 "Frink Park"
 "Flo Ware Park"
 "Leschi Park"
 "Peppi's Playground"
 "Leschi-Lake Dell Natural Area"
 "Leschi Park and South Moorage"
 "North Leschi Moorage"
 "Madrona Park"
 "Powell Barnett Park"]
1.8091741377063915E7 2488664.0659542754 0.13755801689213387
West Seattle Alki
["Me-Kwa-Mooks Natural Area"
 "Me-Kwa-Mooks Park"
 "Emma Schmitz Memorial Overlook"
 "Andover Place"
 "Cormorant Cove"
 "Charles Richey Sr Viewpoint"
 "Schmitz Preserve Park"
 "Schmitz Boulevard"
 "Duwamish Head Greenbelt"
 "Alki Beach Park"
 "Bar-S Playground"
 "Alki Playground"
 "Hamilton Viewpoint Park"]
2.45834691846126E7 3368610.236147073 0.13702745576102698
Capitol Hill Stevens
["Miller Triangle"
 "Seven Hills Park"
 "Washington Park - Japanese Gdn"
 " Lake Washington Boulevard"
 "Washington Park and Arboretum"
 "Washington Park"
 "Lake Washington Boulevard"
 "Pendleton Miller Playfield"
 "Prentis I. Frazier Park"
 "Interlaken Park"
 "Boren Park"]
2.6039592079779927E7 3257296.7380544366 0.12509015994086056
Ballard Sunset Hill
["NW 60th Street Viewpoint"
 "Webster Park"
 "Sunset Hill Park"
 "Golden Gardens Park"]
2.4335620469794728E7 2999062.204514957 0.12323754835991878
West Seattle North Admiral
["Hiawatha Playfield"
 "Schmitz Preserve Park"
 "Schmitz Boulevard"
 "Duwamish Head Greenbelt"
 "Fairmount Park"
 "Belvedere Park"
 "Nantes Park"
 "College Street Ravine"
 "California Place"
 "Hamilton Viewpoint Park"]
4.858141632113909E7 5960598.691665671 0.12269297898324247
Rainier Valley Columbia City
["Hitt's Hill Park"
 "Brighton Playfield"
 "Hillman P-Patch"
 "Genesee Park and Playfield"
 "Lake People Park (Xacua'bs)"
 "Cheasty GS: Cheasty Blvd"
 "Cheasty Boulevard"
 "York Park"
 "Columbia Park"
 "Rainier Playfield"]
3.7406576493219726E7 4344458.806638756 0.11614157760270384
Central Area Atlantic
["Colman Playground"
 "Martin Luther King JR Memorial"
 "Amy Yee Tennis Center"
 "Jimi Hendrix Park"
 "Atlantic Street Park"
 "Sam Smith Park"
 "Benvenuto Viewpoint"
 "Judkins Park and Playfield"
 "Judge Charles M. Stokes Overlook"
 "Pratt Park"
 "Blue Dog Pond"
 "Dr. Blanche Lavizzo Park"
 "Langston Hughes Cultural Arts"]
2.0664986273336366E7 2395983.464898887 0.11594411112628604
Queen Anne West Queen Anne
["Kinnear Park"
 "Marshall Park"
 "Parsons Gardens"
 "Queen Anne Boulevard"
 "SW Queen Anne Greenbelt"
 "West Queen Anne Playfield"
 "Queen Anne Swimming Pool"
 "West Central Grounds Maintenance"
 "12th West & West Howe Park"]
1.797498595288394E7 1964455.447449051 0.10928828832457976
Capitol Hill Broadway
["Plymouth Pillars Park"
 "Bellevue Place"
 "Lakeview Place"
 "Cal Anderson Park"
 "Thomas Street Gardens"
 "Tashkent Park"
 "Williams Place"
 "Broadway Hill Park"
 "Volunteer Parkway"
 "Summit Slope Park"
 "Thomas Street Mini Park"
 "Belmont Place"
 "Summit Place"
 "Bullitt Life Estate"
 "St. Marks Greenbelt"
 "Streissguth Gardens"
 "I-5 Colonnade"
 "Volunteer Park"]
3.0239240521690477E7 3304530.7655596808 0.10927955558901538
Downtown Pike-Market
["Seattle Aquarium"
 "Piers 62 and 63"
 "Waterfront Park"
 "Victor Steinbrueck Park"]
2343359.3260714533 255005.04346191516 0.10882029086397978
Magnolia Briarcliff
["Magnolia Tidelands Park"
 "Magnolia Park"
 "Magnolia Boulevard"
 "Parkmont Place"
 "Eastmont Place"
 "Carleton Center"
 "Carleton Highlands"
 "ARAPAHOE TRIANGLE"
 "Discovery Park"]
2.6550936578728132E7 2713294.302010858 0.10219203733041468
Interbay Interbay
["Myrtle Edwards Park"
 "Ursula Judkins Viewpoint"
 "Smith Cove Park"
 "Magnolia Boulevard"
 "Magnolia Greenbelt"
 "Thorndyke Park"
 "Open Water Park"
 "Interbay P-patch"
 "Interbay Golf"
 "Interbay Athletic Field"
 "Commodore Park"]
3.350394109364654E7 3234156.7950585634 0.09653063757540652
Rainier Valley Dunlap
["Chinook Beach Park"
 "Atlantic City Boat Ramp"
 "Rainier Beach Urban Farm and Wetlands"
 "Beer Sheva Park"
 "Rainier Beach Community Center"
 "Pritchard Island Beach"
 "East Duwamish GS: MLK Way"
 "Rainier Beach Playfield"]
1.9601601215604942E7 1782788.7703944917 0.0909511805073967
Central Area Madrona
["Nora's Woods"
 "Madrona Playground"
 "Madrona Park"
 "Lake Washington Boulevard"
 "Madrona Ravine"
 "Alvin Larkins Park"
 "Madrona Briar Patch"
 "Howell Park"
 "William Grose Park"
 "Harrison Ridge Greenbelt"]
1.3845482808694465E7 1211682.0145605851 0.08751460901021757
Magnolia Southeast Magnolia
["Magnolia Boulevard"
 "Condon Way Centerstrip"
 "Magnolia Park"
 "West Magnolia Playfield"
 " "
 "Lowery C. \"Pop\" Mounger Pool"
 "Ella Bailey Park"
 "Bayview Playground"]
1.8469263888735063E7 1466342.6454210556 0.07939367016762483
Beacon Hill Holly Park
["John C. Little, Sr. Park" "Van Asselt Playground"]
8444235.979074124 656778.4801970643 0.07777831905984671
Beacon Hill South Beacon Hill
["East Duwamish GS: S Chicago St" "Benefit Playground"]
3.844882690015128E7 2989598.1245943466 0.07775524939572562
Rainier Valley Rainier View
["Lakeridge Park"
 "Taylor Creek Headwaters"
 "Lakeridge Playground"
 "Thayer Place"]
1.8248566179783218E7 1398373.180214077 0.07662920836834146
Queen Anne East Queen Anne
["Queen Anne Boulevard"
 "Bhy Kracke Park"
 "Northeast Queen Anne Greenbelt"
 "Highland Place"
 "Highland Drive Parkway"
 "Observatory Courts"
 "East Queen Anne Playground"
 "Wolf Creek Ravine Natural Area"
 "Trolley Hill Park"
 "MacLean Park"
 "Westlake Greenbelt"
 "Thomas C. Wales Park"]
1.9354699596494563E7 1448114.7496615453 0.07481979983423878
Rainier Valley Rainier Beach
["Kubota Gardens Natural Area"
 "Lakeridge Park"
 "Lakeridge Playground"
 "Thayer Place"
 "Kubota Gardens"
 "Fred Hutchinson Playground"
 "Sturtevant Ravine"
 "East Duwamish GS: MLK Way"
 "Fletcher Place"
 "Chinook Beach Park"]
3.312823614223316E7 2442620.8848146023 0.07373229514325559
Central Area Harrison/Denny-Blaine
["Denny Blaine Lake Park"
 "Harrison Ridge Greenbelt"
 "Viretta Park"
 "Stevens Triangle"
 "Denny Blaine Park"
 "Lakeview Park"
 "McGilvra Boulevard"
 "Lake Washington Boulevard"
 "3001 E Madison"]
1.360339567318952E7 946560.209820138 0.06958264190504156
Northeast Ravenna
["Blakeley Crescent Park"
 "Ravenna Ravine"
 "Burke-Gilman Trail"
 "Ravenna Park"
 "Ravenna-Eckstein Park"]
3.678339153768188E7 2537736.5238547004 0.06899136859783514
Lake City Meadowbrook
["Thornton Creek Natural Area: 25th/95th"
 "Meadowbrook Playfield"
 "Meadowbrook Teen Life Center"
 "LaVilla Meadows Natural Area on Thornton Creek"]
1.703484877942584E7 1162909.7193452865 0.06826651262967551
Northwest North Beach/Blue Ridge
["Soundview Playfield"
 "Blue Ridge Places"
 "Carkeek Park"
 "Blue Ridge Circle"
 "North Beach Park"
 "North Beach Ravine: 30th NW Natural Area"
 "Golden Gardens Park"]
3.1062264992039643E7 1942086.5722656162 0.06252237474515514
Northeast Roosevelt
["Ravenna Boulevard"
 "Ravenna Park"
 "Cowen Park"
 "Roosevelt Land-Bank Site"
 "Banner Way Triangles"
 "Froula Playground"
 "Rainbow Point"
 "Maple Leaf Reservoir Park"]
2.1491594324983705E7 1309062.5613024468 0.06091044440480054
Lake City Matthews Beach
["Mock Creek Ravine"
 "Little Brook Creek Natural Area"
 "Chinook Passage Natural Area on Thornton Creek"
 "Burke-Gilman Trail"
 "Matthews Beach Park"]
3.0980978301755752E7 1770241.0308238121 0.05713961042745668
Northeast Bryant
["Burke-Gilman Trail"
 "Burke-Gilman Playground Park"
 "Bryant Playground"]
1.5485078033882016E7 829201.5932133237 0.053548428454735265
Delridge Roxhill
["Roxhill Park"
 "S.W. Community Center and Pool"
 "E.C. Hughes Playground"]
1.87810598448122E7 995987.7545642204 0.053031498903366586
Northeast View Ridge
["Burke-Gilman Trail" "View Ridge Playfield" "Inverness Ravine Park"]
2.561297994427941E7 1288763.708935325 0.05031682028951758
Cascade South Lake Union
["Denny Park"
 "Lake Union Park"
 "Fairview Walkway"
 "Cascade Playground"
 "I-5 Colonnade"
 "Terry Pettus Park"
 "Lynn Street Mini Park"]
1.6107105419750454E7 800866.192857775 0.04972129827099516
Queen Anne North Queen Anne
["Queen Anne Boulevard"
 "Coe Play Park"
 "Queen Anne Bowl Playfield"
 "Mayfair Park"
 "David Rodgers Park"
 "West Ewing Mini Park"
 "Soundview Terrace"]
2.960428833366627E7 1355843.879844315 0.04579890131330861
North Central Wallingford
["Gas Works Park"
 "Harbor Patrol Office and Shop"
 "Waterway 19"
 "Wallingford Steps"
 "Burke-Gilman Trail"
 "Sunnyside Ave N Boat Ramp"
 "Wallingford Playfield"
 "Demonstration Garden"
 "North Passage Point Park"
 "NE 60th Street Park"
 "Meridian Playground"
 "Corliss Place"
 "Keystone Place"
 "Green Lake Park"]
4.2068342614797205E7 1777393.4021316427 0.04225014088162481
Lake City Victory Heights
["Homewood Natural Area on Thornton Creek"
 "Kingfisher Natural Area on Thornton Creek"
 "Virgil Flaim Park"
 "Lake City Park"
 "Victory Heights Playground"
 "Pinehurst Pocket Park"]
2.151273148967749E7 900485.900698212 0.04185827825398623
Beacon Hill Mid-Beacon Hill
["Dearborn Park"
 "Cheasty Greenspace: Mt View"
 "Maple School Ravine"
 "Maple Wood Playfield"
 "Cleveland Playfield"
 "East Duwamish GS: S Spokane St"]
5.262047078955701E7 2161142.3873948674 0.041070373468109767
Central Area Mann
["Garfield Teen Life Center"
 "Garfield Playfield"
 "Homer Harris Park"
 "Gerber Park"
 "Plum Tree Park"
 "Julia Lee's Park"]
1.113382886245558E7 443902.819098556 0.03986973615118534
Cascade Eastlake
["I-5 Colonnade"
 "Fairview Park"
 "South Passage Point Park"
 "Rogers Playground"
 "Roanoke Street Mini Park"
 "Terry Pettus Park"
 "Lynn Street Mini Park"]
7426907.961769626 293104.7959594849 0.039465252224513386
Northgate Maple Leaf
["Sacajawea Playground"
 "Maple Leaf Community Garden"
 "Beaver Pond Natural Area on Thornton Creek"
 "Maple Leaf Reservoir Park"
 "Kingfisher Natural Area on Thornton Creek"
 "Victory Creek Confluence Natural Area on TC"
 "Northgate Park"
 "Northgate Community Center"]
3.4380470783073254E7 1130968.2364097128 0.03289565880425725
Northeast Laurelhurst
["Union Bay Boglands #2"
 "Union Bay Boglands #1"
 "LAURELHURST TRIANGLE"
 "Belvoir Place"
 "Laurelhurst Playfield"
 "Laurelhurst Recreation Center"
 "Sun Park"]
1.905177681936156E7 622689.0135556267 0.03268403884108136
Northeast Wedgwood
["Dahl (Waldo J.) Playfield"
 "Picardo (Rainie) P-Patch"
 "Thornton Creek Natural Area: 25th/95th"
 "Wedgwood Square"
 "8605 35th Ave NE"
 "Inverness Ravine Park"
 "Maple Springs Natural Area"]
3.059971362703256E7 968985.0098010622 0.031666473144540686
Downtown Yesler Terrace
["Yesler Terrace Park" "Horiuchi Park" "Boren Place"]
5348937.247801803 159300.53646585828 0.02978171720584764
Downtown Belltown
["Myrtle Edwards Park"
 "Bell Street Park Boulevard"
 "Belltown Cottage Park"
 "Belltown P-patch"
 "Regrade Park"
 "Alaskan Way Boulevard"
 "Tilikum Place"]
9845864.786277873 279689.8893769705 0.028406838347686095
Capitol Hill Portage Bay
["Roanoke Park" "Bagley Viewpoint"]
4421635.267367266 121026.6277003076 0.027371463357349548
Greater Duwamish South Park
["South Park Meadow"
 "Marra-Desimone Park"
 "Cesar Chavez Park"
 "South Park Playground"
 "Duwamish Waterway Park"]
2.9423452152724065E7 788757.1095861244 0.0268070893072654
West Seattle Arbor Heights
["Seola Park" "Seola Beach Greenbelt" "Fauntleroy Park"]
2.619731405785146E7 661354.2410716552 0.0252451163356361
Lake City Cedar Park
["Lake City Memorial Triangle"
 "Burke-Gilman Trail"
 "Lake City Urban Hub Village"
 "Cedar Park"
 "University Lake Shore Place"
 "NE 130th Street End"]
2.04414858490784E7 500421.66464288835 0.02448068933626221
University District University District
["Burke-Gilman Trail"
 "Ravenna Woods"
 "Christie Park"
 "17th Avenue NE Centerstrip"
 "North Passage Point Park"
 "Northlake Park"
 "University Playground"]
1.3686254858800735E7 324977.58184178185 0.023744814428383235
Northgate Licton Springs
["Mineral Springs Park" "Licton Springs Park"]
2.1704706262052845E7 513945.6292462934 0.023678994916639065
Northgate Haller Lake
["Haller Lake Community St End" "Northacres Park" "Helene Madison Pool"]
4.720308108008111E7 1112625.044392759 0.023571025851155034
Northeast Windermere
["Burke-Gilman Trail" "University Circle" "Warren G. Magnuson Park"]
2.2363966623912185E7 500567.5192937572 0.022382769913389885
Ballard Loyal Heights
["Salmon Bay Park" "Loyal Heights Playfield"]
2.1320655545884836E7 421263.7501266854 0.019758480184629914
Downtown International District
["Donnie Chin International Children's Park"
 "Hing Hay Park Addition"
 "ID/Chinatown Community Center"
 "Beacon Place"
 "Chinatown/ID Hub Urban Village"
 "Hing Hay Park"
 "Kobe Terrace"]
6169375.816795917 121130.99413208748 0.019634238167548886
Rainier Valley Brighton
["Othello Park"]
1.8366938275487844E7 342712.9789050467 0.01865923289797433
Downtown Central Business District
["Waterfront Park" "Jim Ellis Freeway Park" "Westlake Park"]
9477398.618861396 176559.42602316735 0.018629524105041706
North Central Fremont
["A. B. Ernst Park"
 "Fremont Canal Park"
 "Burke-Gilman Trail"
 "Fremont Peak Park"
 "Troll's Knoll Park"
 "B.F. Day Playground"
 "Ross Playground"]
2.650375657209128E7 443605.6587439842 0.016737463519081116
Northwest Bitter Lake
["Bitter Lake Playfield" "Bitter Lake Open Space Park"]
2.769033644488096E7 463326.8142235621 0.016732437149900217
Northwest Greenwood
["Alice Ball Park"
 "Greenwood Park"
 "6th Avenue NW Pocket Park"
 "Sandel Playground"
 "Carkeek Park"]
4.204456367454267E7 689596.1664853458 0.01640155364254346
University District University Heights
["17th Avenue NE Centerstrip"
 "Ravenna Boulevard"
 "Park Home Circle"
 "University Heights"
 "Ravenna Park"]
1.037574805292391E7 166849.97798407465 0.016080766141681316
West Seattle Gatewood
["Orchard Street Ravine"
 "Myrtle Reservoir Park"
 "Lincoln Park"
 "Lowman Beach Park"
 "Pelly Place Natural Area"
 "Watton Life Estate"
 nil]
2.2821707469523415E7 355085.68614532915 0.015559120044787095
West Seattle Fairmount Park
["Fairmount Playground"]
1.6153900097573552E7 237376.26008061314 0.014694671791134142
Downtown First Hill
["Jim Ellis Freeway Park" "First Hill Park" "Boylston Place"]
9517568.473671103 126769.23408250557 0.0133194979824094
Downtown Pioneer Square
["Union Station Square"
 "Occidental Square"
 "City Hall Park"
 "Prefontaine Place"
 "Pioneer Square"]
7545979.087288558 95347.44250189843 0.0126355296508195
Ballard Ballard
["Bergen Place"
 "Ballard Corners Park"
 "Marvins Garden"
 "Ballard Commons Park"
 "Thyme Patch Park"
 "Ballard Playground"]
2.255213297047855E7 244344.9612760165 0.01083467189537556
Cascade Westlake
["Lake Union Park"]
3645184.079110308 37961.61985636592 0.010414184587800388
Ballard West Woodland
["Greenwood Triangle"
 "14th Avenue NW Boat Ramp"
 "Gilman Playground"
 "Gemenskap Park"]
2.2199366873893585E7 226099.72709449235 0.010184962858575269
Central Area Minor
["Spruce Street Mini Park"
 "Garfield Playfield"
 "Cayton Corner Park"
 "Langston Hughes Annex"
 "12th Ave Square Park"
 "Firehouse Mini Park"
 "Spring Street Mini Park"
 "T.T. Minor Playground"
 "McGilvra Place"]
1.7933144708720244E7 172158.54773067622 0.009600019992420052
Greater Duwamish Industrial District
["Herrings House Park (Tulaltx)"
 "Alki Beach Park"
 "Seacrest Park"
 "Don Armeni Boat Ramp"]
6.243413101303743E7 559378.0064992205 0.00895949054504197
Ballard Whittier Heights
["Kirke Park" "Ballard Swimming Pool" "Baker Park on Crown Hill"]
1.4195687492422596E7 108946.50009691996 0.007674619503639655
Delridge South Delridge
["Longfellow Creek GS: South"]
1.792331622408078E7 132742.1724476857 0.007406116746929937
Queen Anne Lower Queen Anne
["Blaine Place"
 "Counterbalance Park"
 "Kinnear Place"
 "Kerry Park (Franklin Place)"
 "Kerry Park and Viewpoint"
 "Ward Springs Park"]
1.7515624457317874E7 106952.95177903834 0.006106145518229259
Northwest Crown Hill
["Crown Hill Glen" "Crown Hill Park"]
1.586575041985613E7 94943.40486711139 0.005984173603808166
University District University of Washington
["Union Bay Boglands #2"
 "Union Bay Boglands #1"
 "Fritz Hedges Waterway Park"]
2.5523675124439575E7 142125.03524102044 0.005568360925614982
Greater Duwamish Georgetown
["Georgetown Pump Station" "Oxbow Park" "Georgetown Playfield"]
5.130507264703818E7 281438.2271119965 0.005485582859383083
Lake City Olympic Hills
["Thornton Creek Addition: North Branch"
 "Albert Davis Park"
 "Little Brook Park"]
2.5836742164596498E7 141195.81351923634 0.005464923271662082
West Seattle Genesee
["West Seattle Junction"
 "Junction Plaza Park"
 "Ercolini Park"
 "Dakota Place Park"
 "48th Ave SW/SW Charlestown St"
 "Fauntleroy Place"]
2.1164976581792817E7 91891.1780685815 0.00434166216595916
West Seattle Seaview
["Lowman Beach Park" "Morgan Junction Park"]
1.846306179837895E7 51860.33722001134 0.002808869828110777
Downtown Denny Triangle
["McGraw Square" "Westlake Square" "Urban Triangle Park"]
5128172.310711999 11668.172603196248 0.002275308218256073
Greater Duwamish Harbor Island
[]
1.7832300735864956E7 0.0 0.0
Greater Duwamish SODO
[]
4.9603167591402024E7 0.0 0.0
(defn plot-neighborhoods-with-park-proportions [data]
  (kind/echarts
   {:title {:text "Neighborhoods by park proportion"}
    :tooltip {}
    :xAxis {:data (:S_HOOD data)
            :axisLabel {:rotate 90}}
    :yAxis {}
    :series [{:type "bar"
              :data (:park-proportion data)}]
    :grid {:containLabel true}}))
(delay
  (-> neighborhoods-with-park-proportions
      (tc/order-by [:park-proportion] :desc)
      plot-neighborhoods-with-park-proportions))

Note you may hover to see the neighborhood names. Let us take the ten most park-intense neighborhoods.

(delay
  (-> neighborhoods-with-park-proportions
      (tc/order-by [:park-proportion] :desc)
      (tc/head 10)
      plot-neighborhoods-with-park-proportions))

Representing park proportions as colors:

We will use Clojure2d’s clojure.color functionality.

(def gradient
  (color/gradient [:purple :yellow]))
(delay
  (-> 0.4
      gradient
      color/format-hex))
"#b3664d"

A choropleth coloured by park proportions

(def neighborhoods-coloured-by-park-proportion
  (-> neighborhoods-with-park-proportions
      (tc/map-columns :feature
                      [:feature :park-names-str :park-proportion]
                      (fn [feature park-names-str park-proportion]
                        (let [color (-> park-proportion
                                        gradient
                                        color/format-hex)]
                          (-> feature
                              (update-in
                               [:properties :style]
                               (fn [style]
                                 (-> style
                                     (assoc :color color
                                            :fillColor color
                                            :opacity 0.7
                                            :fillOpacity 0.7))))
                              (update-in
                               [:properties :tooltip]
                               str
                               (hiccup/html
                                [:div
                                 [:p [:b "Park proportion: "]
                                  (format "%.01f%%"
                                          (* 100 park-proportion))]
                                 [:p {:style {:max-width "200px"
                                              :text-wrap :wrap}}
                                  [:b "Parks: "]
                                  park-names-str]]))))))))
(delay
  (-> neighborhoods-coloured-by-park-proportion
      :feature
      vec
      Seattle-choropleth-map))

Another option: use opacity rather than color to higlight differences.

(def neighborhoods-highlighted-by-park-proportion
  (-> neighborhoods-coloured-by-park-proportion
      (tc/map-columns :feature
                      [:feature :park-proportion]
                      (fn [feature park-proportion]
                        (-> feature
                            (update-in
                             [:properties :style]
                             (fn [style]
                               (-> style
                                   (assoc :color "yellow"
                                          :opacity park-proportion
                                          :fillColor "yellow"
                                          :fillOpacity park-proportion)))))))))
(delay
  (-> neighborhoods-highlighted-by-park-proportion
      :feature
      vec
      Seattle-choropleth-map))

In this case the choropleth mainly helps us in pointing out a few park-intense neighborhoods.

Let us focus on the ten most park-intense neighborhoods:

(delay
  (-> neighborhoods-coloured-by-park-proportion
      (tc/order-by [:park-proportion] :desc)
      (tc/head 10)
      :feature
      vec
      Seattle-choropleth-map))
(kind/md
 "TODO: The area proportions would be best represented in a bar chart to accompany the table
TODO: summarizing the quartiles of values might be useful as well

TODO: An interesting map would show just one L_HOOD and all the parks,
perhaps choosing the \"winner\" with most park space and showing where in Seattle it is, and what parks are there.

## Conclusion

Park access is fairly uniform and high in Seattle.
TODO: can we compare it to another city?
"
 )

TODO: The area proportions would be best represented in a bar chart to accompany the table TODO: summarizing the quartiles of values might be useful as well

TODO: An interesting map would show just one L_HOOD and all the parks, perhaps choosing the “winner” with most park space and showing where in Seattle it is, and what parks are there.

Conclusion

Park access is fairly uniform and high in Seattle. TODO: can we compare it to another city?

Draft text for the story to be told.

  • Intersections and spatial joins

  • In what context would these visualizations be useful?

  • Using the REPL to dive into cases and their details

  • Doing that in self-documenting way

  • How does this compose with GUI-based explorations?

  • Choice of colors

source: projects/geography/seattle-parks/notebooks/index.clj