Geokodning for dataforskere - KDnuggets

Geokodning for dataforskere – KDnuggets

Kildeknude: 2713218

Når dataforskere skal vide alt, hvad der er at vide om "hvor" af deres data, henvender de sig ofte til Geographic Information Systems (GIS). GIS er et kompliceret sæt af teknologier og programmer, der tjener en bred vifte af formål, men University of Washington giver en ret omfattende definition og siger "et geografisk informationssystem er et komplekst arrangement af tilknyttede eller forbundne ting eller objekter, hvis formål er at formidle viden om træk på jordens overflade” (Lawler et al.). GIS omfatter en bred vifte af teknikker til behandling af rumlige data fra indsamling til visualisering, hvoraf mange er værdifulde værktøjer, selvom du ikke er GIS-specialist. Denne artikel giver et omfattende overblik over geokodning med demonstrationer i Python af flere praktiske anvendelser. Specifikt vil du bestemme den nøjagtige placering af en pizzeria i New York City, New York ved hjælp af dens adresse og forbinde den med data om nærliggende parker. Mens demonstrationerne bruger Python-kode, kan kernekoncepterne anvendes til mange programmeringsmiljøer for at integrere geokodning i din arbejdsgang. Disse værktøjer giver grundlaget for at transformere data til rumlige data og åbner døren for mere kompleks geografisk analyse. 

 

XXXXX

Geokodning er mest almindeligt defineret som transformation af adressedata til kortlægningskoordinater. Normalt involverer dette at detektere et gadenavn i en adresse, matche den gade med grænserne for dens modstykke i den virkelige verden i en database, og derefter estimere hvor på gaden adressen skal placeres ved hjælp af gadenummeret. Lad os som et eksempel gennemgå processen med en simpel manuel geokode for adressen på en pizzeria i New York på Broadway: 2709 Broadway, New York, NY 10025. Den første opgave er at finde passende formfiler til lokalitetens vejsystem af din adresse. Bemærk, at i dette tilfælde er byen og staten for adressen "New York, NY." Heldigvis udgiver byen New York detaljerede vejoplysninger om NYC åbne data side (CSCL PUB). For det andet, undersøg gadenavnet "Broadway". Du ved nu, at adressen kan ligge på enhver gade kaldet "Broadway" i New York, så du kan udføre følgende Python-kode for at forespørge NYC Open Data SODA API for alle gader med navnet "Broadway."

import geopandas as gpd
import requests
from io import BytesIO # Request the data from the SODA API
req = requests.get( "https://data.cityofnewyork.us/resource/gdww-crzy.geojson?stname_lab=BROADWAY"
)
# Convert to a stream of bytes
reqstrm = BytesIO(req.content)
# Read the stream as a GeoDataFrame
ny_streets = gpd.read_file(reqstrm)

 

Der er over 700 resultater af denne forespørgsel, men det betyder ikke, at du skal tjekke 700 gader for at finde din pizza. Når du visualiserer dataene, kan du se, at der er 3 hovedgader på Broadway og et par mindre.

 

XXXXX
 

Grunden til dette er, at hver gade er opdelt i sektioner, der svarer nogenlunde til en blok, hvilket giver mulighed for et mere detaljeret kig på dataene. Det næste trin i processen er at bestemme præcis, hvilken af ​​disse sektioner adressen er på ved hjælp af postnummer og vejnummer. Hvert gadesegment i datasættet indeholder adresseområder for adresserne på bygninger på både venstre og højre side af gaden. På samme måde indeholder hvert segment postnummeret for både venstre og højre side af gaden. For at finde det korrekte segment anvender følgende kode filtre til at finde det gadesegment, hvis postnummer matcher adressens postnummer, og hvis adresseområde indeholder adressens gadenummer.

# Address to be geocoded
address = "2709 Broadway, New York, NY 10025"
zipcode = address.split(" ")[-1]
street_num = address.split(" ")[0] # Find street segments whose left side address ranges contain the street number
potentials = ny_streets.loc[ny_streets["l_low_hn"] street_num]
potentials = potentials.loc[potentials["l_high_hn"] > street_num]
# Find street segments whose zipcode matches the address'
potentials = potentials.loc[potentials["l_zip"] == zipcode]

 

Dette indsnævrer listen til det ene gadesegment, der ses nedenfor.

 

XXXXX
 

Den sidste opgave er at bestemme, hvor adressen ligger på denne linje. Dette gøres ved at placere gadenummeret inden for adresseområdet for segmentet, normalisere for at bestemme, hvor langt langs linjen adressen skal være, og anvende denne konstant på koordinaterne for linjens endepunkter for at få adressens koordinater. Følgende kode beskriver denne proces.

import numpy as np
from shapely.geometry import Point # Calculate how far along the street to place the point
denom = ( potentials["l_high_hn"].astype(float) - potentials["l_low_hn"].astype(float)
).values[0]
normalized_street_num = ( float(street_num) - potentials["l_low_hn"].astype(float).values[0]
) / denom # Define a point that far along the street
# Move the line to start at (0,0)
pizza = np.array(potentials["geometry"].values[0].coords[1]) - np.array( potentials["geometry"].values[0].coords[0]
)
# Multiply by normalized street number to get coordinates on line
pizza = pizza * normalized_street_num
# Add starting segment to place line back on the map
pizza = pizza + np.array(potentials["geometry"].values[0].coords[0])
# Convert to geometry array for geopandas
pizza = gpd.GeoDataFrame( {"address": , "geometry": [Point(pizza[0], pizza[1])]}, crs=ny_streets.crs, geometry="geometry",
)

 

Efter at have afsluttet geokodningen af ​​adressen, er det nu muligt at plotte placeringen af ​​denne pizzeria på et kort for at forstå dens placering. Da koden ovenfor så på informationer vedrørende venstre side af et gadesegment, vil den faktiske placering være lidt til venstre for det plottede punkt i en bygning på venstre side af vejen. Du ved endelig, hvor du kan få noget pizza.

 

XXXXX
 

Denne proces dækker over det, der oftest omtales som geokodning, men det er ikke den eneste måde, udtrykket bruges på. Du kan også se geokodning referere til processen med at overføre vartegnsnavne til koordinater, postnumre til koordinater eller koordinater til GIS-vektorer. Du kan endda høre omvendt geokodning (som vil blive dækket senere) omtalt som geokodning. En mere lempelig definition af geokodning, der omfatter disse, ville være "overførslen mellem omtrentlige, naturlige sprogbeskrivelser af steder og geografiske koordinater." Så hver gang du har brug for at flytte mellem disse to slags data, skal du overveje geokodning som en løsning.

Som et alternativ til at gentage denne proces, når du har brug for at geokode adresser, kan en række API-endepunkter, som f.eks. US Census Bureau Geokoder og Google Geocoding API, leverer en nøjagtig geokodningstjeneste gratis. Nogle betalte muligheder, som f.eks Esri's ArcGIS, Geocodioog Smarty tilbyder endda tagnøjagtighed for udvalgte adresser, hvilket betyder, at de returnerede koordinater lander nøjagtigt på bygningens tag i stedet for på en nærliggende gade. De følgende afsnit skitserer, hvordan du bruger disse tjenester til at passe geokodning ind i din datapipeline ved at bruge US Census Bureau Geocoder som eksempel.

For at få den højest mulige nøjagtighed ved geokodning, bør du altid begynde med at sikre, at dine adresser er formateret, så de passer til standarderne for din valgte tjeneste. Dette vil afvige lidt mellem hver tjeneste, men et almindeligt format er USPS-formatet "PRIMARY# STREET, CITY, STATE, ZIP", hvor STATE er en forkortelseskode, PRIMARY# er gadenummeret og alle omtaler af suitenumre, bygning numre, og postbokse fjernes. 

Når din adresse er formateret, skal du indsende den til API'et til geokodning. I tilfældet med US Census Bureau Geocoder kan du enten manuelt indsende adressen via fanen One Line Address Processing eller bruge leveret REST API at indsende adressen programmatisk. US Census Bureau Geocoder giver dig også mulighed for at geokode hele filer ved hjælp af batch-geokoderen og angive datakilden ved hjælp af benchmark-parameteren. For at geokode pizzabaren fra tidligere, dette link kan bruges til at videregive adressen til REST API, hvilket kan gøres i Python med følgende kode.

# Submit the address to the U.S. Census Bureau Geocoder REST API for processing
response = requests.get( "https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address=2709+Broadway%2C+New+York%2C+NY+10025&benchmark=Public_AR_Current&format=json"
).json()

 

De returnerede data er en JSON-fil, som let afkodes til en Python-ordbog. Det indeholder et "tigerLineId" felt, som kan bruges til at matche shapefilen for den nærmeste gade, et "side" felt, som kan bruges til at bestemme, hvilken side af den gade adressen er på, og "fromAddress" og "toAddress" felterne som indeholder adresseområdet for gadesegmentet. Vigtigst er det, at det indeholder et "koordinat"-felt, der kan bruges til at lokalisere adressen på et kort. Følgende kode udtrækker koordinaterne fra JSON-filen og behandler den til en GeoDataFrame for at forberede den til rumlig analyse.

# Extract coordinates from the JSON file
coords = response["result"]["addressMatches"][0]["coordinates"]
# Convert coordinates to a Shapely Point
coords = Point(coords["x"], coords["y"])
# Extract matched address
matched_address = response["result"]["addressMatches"][0]["matchedAddress"]
# Create a GeoDataFrame containing the results
pizza_point = gpd.GeoDataFrame( {"address": [matched_address], "geometry": coords}, crs=ny_streets.crs, geometry="geometry",
)

 

Visualisering af dette punkt viser, at det er lidt væk fra vejen til venstre for det punkt, der blev geokodet manuelt.

 

XXXXX

Omvendt geokodning er processen med at tage geografiske koordinater og matche dem med naturlige sprogbeskrivelser af en geografisk region. Når det anvendes korrekt, er det en af ​​de mest kraftfulde teknikker til at vedhæfte eksterne data i datavidenskabsværktøjssættet. Det første trin i omvendt geokodning er at bestemme dine målgeografier. Dette er den region, der vil indeholde dine koordinatdata. Nogle almindelige eksempler er folketællinger, postnumre og byer. Det andet trin er at bestemme, hvilken, om nogen, af disse regioner punktet er i. Når du bruger fælles regioner, US Census Geokoder kan bruges til at vende geokode ved at lave små ændringer i REST API-anmodningen. En anmodning om at bestemme, hvilke Census-geografier, der indeholder pizzaboden fra før, er linket link.. Resultatet af denne forespørgsel kan behandles ved hjælp af de samme metoder som før. Men kreativt at definere regionen, så den passer til et analysebehov og manuelt omvendt geokodning til den, åbner der op for mange muligheder. 

For manuelt at vende geokoden skal du bestemme placeringen og formen af ​​en region og derefter bestemme, om punktet er på det indre af det pågældende område. At bestemme om et punkt er inde i en polygon er faktisk et ret vanskeligt problem, men strålekastningsalgoritme, hvor en stråle, der starter ved punktet og bevæger sig uendeligt i en retning, skærer grænsen for regionen et ulige antal gange, hvis den er inde i regionen og et lige antal gange ellers (Shimrat), kan bruges til at løse det i de fleste sager. For de matematisk tilbøjelige er dette faktisk en direkte anvendelse af Jordan kurvesætning (Hosch). Som en note, hvis du bruger data fra hele verden, kan strålekastningsalgoritmen faktisk mislykkes, da en stråle til sidst vil pakke sig rundt om jordens overflade og blive en cirkel. I dette tilfælde skal du i stedet finde viklingstallet (Weisstein) for regionen og punktet. Punktet er inden for området, hvis viklingstallet ikke er nul. Heldigvis giver Pythons geopandas-bibliotek den nødvendige funktionalitet til både at definere det indre af en polygonal region og teste, om et punkt er inde i det uden al den komplekse matematik.

Mens manuel geokodning kan være for kompleks til mange applikationer, kan manuel omvendt geokodning være en praktisk tilføjelse til dit færdighedssæt, da det giver dig mulighed for nemt at matche dine point til meget tilpassede områder. Antag for eksempel, at du vil tage dit stykke pizza med til en park og have en picnic. Du vil måske gerne vide, om pizzabaren er inden for kort afstand fra en park. New York City leverer shapefiler til deres parker som en del af Parks Properties datasæt (NYC Parks Open Data Team), og de kan også tilgås via deres SODA API ved hjælp af følgende kode.

# Pull NYC park shapefiles
parks = gpd.read_file( BytesIO( requests.get( "https://data.cityofnewyork.us/resource/enfh-gkve.geojson?$limit=5000" ).content )
)
# Limit to parks with green area for a picnic
parks = parks.loc[ parks["typecategory"].isin( [ "Garden", "Nature Area", "Community Park", "Neighborhood Park", "Flagship Park", ] )
]

 

Disse parker kan føjes til visualiseringen for at se, hvilke parker der er i nærheden af ​​pizzaboden.

 

XXXXX
 

Der er helt klart nogle muligheder i nærheden, men det kan være svært og beregningsmæssigt dyrt at finde ud af afstanden ved hjælp af shapefilerne og pointen. I stedet kan omvendt geokodning anvendes. Det første trin, som nævnt ovenfor, er at bestemme den region, du vil knytte punktet til. I dette tilfælde er regionen "1/2-mile afstand fra en park i New York City." Det andet trin er beregning om punktet ligger inde i et område, hvilket kan gøres matematisk ved hjælp af de tidligere nævnte metoder eller ved at anvende funktionen "indeholder" i geopander. Følgende kode bruges til at tilføje en 1/2-mile-buffer til parkernes grænser, før den testes for at se, hvilke parkers bufferområder, der nu indeholder punktet.

# Project the coordinates from latitude and longitude into meters for distance calculations
buffered_parks = parks.to_crs(epsg=2263)
pizza_point = pizza_point.to_crs(epsg=2263)
# Add a buffer to the regions extending the border by 1/2 mile = 2640 feet
buffered_parks = buffered_parks.buffer(2640)
# Find all parks whose buffered region contains the pizza parlor
pizza_parks = parks.loc[buffered_parks.contains(pizza_point["geometry"].values[0])]

 

Denne buffer afslører de nærliggende parker, som er fremhævet med blåt på billedet nedenfor

 

XXXXX
 

Efter vellykket omvendt geokodning har du erfaret, at der er 8 parker inden for en halv kilometer fra pizzabaren, hvor du kan holde din picnic. Nyd den skive.
 

XXXXX
Pizza Slice af j4p4n

Kilder

  1. Lawler, Josh og Schiess, Peter. ESRM 250: Introduktion til geografiske informationssystemer i skovressourcer. Definitioner af GIS, 12. februar 2009, University of Washington, Seattle. Klasseforedrag. https://courses.washington.edu/gis250/lessons/introduction_gis/definitions.html
  2. CSCL PUB. New York OpenData. https://data.cityofnewyork.us/City-Government/road/svwp-sbcd
  3. US Census Bureau Geokoder dokumentation. august 2022. https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf 
  4. Shimrat, M., "Algorithm 112: Position af punkt i forhold til polygon" 1962, Kommunikation af ACM Bind 5 hæfte 8, august 1962. https://dl.acm.org/doi/10.1145/368637.368653 
  5. Hosch, William L.. "Jordan curve theorem". Encyclopedia Britannica13. april 2018, https://www.britannica.com/science/Jordan-curve-theorem
  6. Weisstein, Eric W. "Konturviklingsnummer." Fra MathWorld–En Wolfram-webressource. https://mathworld.wolfram.com/ContourWindingNumber.html
  7. NYC Parks Open Data Team. Parks ejendomme. 14. april 2023. https://nycopendata.socrata.com/Recreation/Parks-Properties/enfh-gkve
  8. j4p4n, "Pizza Slice." Fra OpenClipArt. https://openclipart.org/detail/331718/pizza-slice

 
 
Evan Miller er Data Science Fellow hos Tech Impact, hvor han bruger data til at støtte nonprofit- og offentlige myndigheder med en mission om socialt gode. Tidligere brugte Evan maskinlæring til at træne autonome køretøjer på Central Michigan University.
 

Tidsstempel:

Mere fra KDnuggets