Created
January 22, 2019 16:38
-
-
Save b5/7fc378b6ee504e929ab390bca8f038f6 to your computer and use it in GitHub Desktop.
Starlark Geospatial sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this is a Qri starlark transform script, use it with qri: https://qri.io | |
load("http.star", "http") | |
load("geo.star", "geo") | |
def download(ctx): | |
# Download list of 311 complaints, currently capped to 10000 responses for testing purposes | |
complaints = http.get("https://data.cityofnewyork.us/resource/fhrw-4uyv.json?$offset=0&$limit=10000") | |
# Download the New York Borough Boundaries | |
boros = http.get("http://data.beta.nyc//dataset/68c0332f-c3bb-4a78-a0c1-32af515892d6/resource/7c164faa-4458-4ff2-9ef0-09db00b509ef/download/42c737fd496f4d6683bba25fb0e86e1dnycboroughboundaries.geojson") | |
return { | |
"complaints" : complaints.json(), | |
# send boros over as a JSON string, parseGeoJSON will do the decoding | |
"boros": boros.text(), | |
} | |
def transform(ds, ctx): | |
complaints = ctx.download["complaints"] | |
boundaries, properties = geo.parseGeoJSON(ctx.download["boros"]) | |
# bouroughs data specifies a number of polygons for each borough, | |
# combine them all into MultiPolygons, one for each borough | |
boro_names = [ boro['borough'] for boro in properties] | |
geoms = reduce(append_polygon, zip(boro_names, boundaries), {}) | |
geoms = [geo.MultiPolygon(geoms[x]) for x in geoms] | |
boro_names = list(set(boro_names)) | |
# dict of complaint-counts, keyed by borough name | |
boro_counts = dict(zip(boro_names, [0]*len(boro_names))) | |
for complaint in complaints: | |
# only use complaints that have lat & lng values | |
if 'latitude' in complaint and 'longitude' in complaint: | |
point = geo.Point(float(complaint['longitude']), float(complaint['latitude'])) | |
for boro_name, geom in zip(boro_names, geoms): | |
if geo.within(point, geom): | |
boro_counts[boro_name] += 1 | |
ds.set_body(boro_counts) | |
def append_polygon(acc, prop): | |
polys = acc.get(prop[0], []) | |
polys.append(prop[1]) | |
acc[prop[0]] = polys | |
return acc | |
def reduce(fn, l, v): | |
for _, el in enumerate(l): | |
v = fn(v, el) | |
return v |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment