Add UPS service area layers
Requested-By: Eric Villnow
This commit is contained in:
parent
2faf722f03
commit
7e5cb5ff1d
7 changed files with 180 additions and 0 deletions
77
layers/ups/get_data.py
Executable file
77
layers/ups/get_data.py
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i "python3 -i" -p python3Packages.shapely python3Packages.fiona python3Packages.requests
|
||||
|
||||
print("Starting…")
|
||||
|
||||
from collections import defaultdict
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
import io
|
||||
|
||||
import requests
|
||||
import fiona
|
||||
from shapely.geometry import shape, mapping
|
||||
from shapely.ops import unary_union
|
||||
|
||||
print("Completed imports")
|
||||
|
||||
# Create lists of zip codes per center and centers per state
|
||||
print("parsing URC255V.csv…", end="", flush=True)
|
||||
if not os.path.exists("URC255V.csv"):
|
||||
print("Warning: URC255V.csv not found. Please download it from UPS and place it in this directory.")
|
||||
exit(1)
|
||||
# Read URC255V.csv into a dict
|
||||
reader = csv.DictReader(open("URC255V.csv", encoding="utf-8"))
|
||||
centers_by_state = defaultdict(set)
|
||||
zips_by_center = defaultdict(list)
|
||||
# "CountryCode","PostalLow","PostalHigh","URC25.5V","06/2023"
|
||||
# "US","55336","55336"," MN 553 0-01"
|
||||
# "US","55337","55337"," MN 551 9-02"
|
||||
for row in reader:
|
||||
if row["CountryCode"] == "US":
|
||||
center = row["URC25.5V"].strip().split('-')[0]
|
||||
state = center.split(" ")[0]
|
||||
centers_by_state[state].add(center)
|
||||
for zip in range(int(row["PostalLow"]), int(row["PostalHigh"]) + 1):
|
||||
zips_by_center[center].append(str(zip).zfill(5))
|
||||
print("complete.")
|
||||
|
||||
# Fetch and parse zip code geometries
|
||||
# TODO: could also get as geopackage or kml file I think? Not sure if either of those is easier to open.
|
||||
print("fetching zip code data…", end="", flush=True)
|
||||
res = requests.get("https://www2.census.gov/geo/tiger/GENZ2020/shp/cb_2020_us_zcta520_500k.zip")
|
||||
res.raise_for_status()
|
||||
print("complete.")
|
||||
print("parsing zip code data…", end="", flush=True)
|
||||
# Yeah, this loads into memory, but the file is only 60ish MiB.
|
||||
zip_data = list(fiona.io.ZipMemoryFile(io.BytesIO(res.content)).open())
|
||||
zips = {}
|
||||
for zip in zip_data: # PIVOT! PIVOT!
|
||||
zips[zip.properties["NAME20"]] = zip.geometry
|
||||
print("complete.")
|
||||
|
||||
# Save output
|
||||
print("writing output files…")
|
||||
os.makedirs("states", exist_ok=True)
|
||||
for state, centers in centers_by_state.items():
|
||||
print(" "+ state)
|
||||
features = []
|
||||
for center in centers:
|
||||
center_zips = zips_by_center[center]
|
||||
features.append({
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"center": center,
|
||||
},
|
||||
"geometry": mapping(unary_union([shape(zips[zip]) for zip in center_zips if zip in zips])),
|
||||
})
|
||||
with open(f"states/{state}.geojson", "w", encoding="utf-8") as f:
|
||||
json.dump(
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": features,
|
||||
},
|
||||
f,
|
||||
)
|
||||
print("complete.")
|
||||
Loading…
Add table
Add a link
Reference in a new issue