Geocodificación para científicos de datos - KDnuggets

Geocodificación para científicos de datos – KDnuggets

Nodo de origen: 2713218

Cuando los científicos de datos necesitan saber todo lo que hay que saber sobre el “dónde” de sus datos, a menudo recurren a los Sistemas de Información Geográfica (SIG). Los SIG son un conjunto complicado de tecnologías y programas que sirven para una amplia variedad de propósitos, pero la Universidad de Washington proporciona una definición bastante completa, diciendo que “un sistema de información geográfica es una disposición compleja de cosas u objetos asociados o conectados, cuyo propósito es comunicar conocimientos sobre las características de la superficie de la tierra” (Lawler et al). SIG abarca una amplia gama de técnicas para procesar datos espaciales desde la adquisición hasta la visualización, muchas de las cuales son herramientas valiosas incluso si no es un especialista en SIG. Este artículo proporciona una descripción general completa de la geocodificación con demostraciones en Python de varias aplicaciones prácticas. Específicamente, determinará la ubicación exacta de una pizzería en la ciudad de Nueva York, Nueva York, utilizando su dirección y la conectará con datos sobre parques cercanos. Si bien las demostraciones utilizan código Python, los conceptos básicos se pueden aplicar a muchos entornos de programación para integrar la codificación geográfica en su flujo de trabajo. Estas herramientas proporcionan la base para transformar datos en datos espaciales y abren la puerta a análisis geográficos más complejos. 

 

XXXXX

La geocodificación se define más comúnmente como la transformación de datos de direcciones en coordenadas cartográficas. Por lo general, esto implica detectar el nombre de una calle en una dirección, hacer coincidir esa calle con los límites de su contraparte del mundo real en una base de datos y luego estimar en qué lugar de la calle colocar la dirección utilizando el número de calle. Como ejemplo, repasemos el proceso de una codificación geográfica manual simple para la dirección de una pizzería en Nueva York en Broadway: 2709 Broadway, New York, NY 10025. La primera tarea es encontrar archivos de forma apropiados para el sistema de carreteras de la ubicación. de su dirección. Tenga en cuenta que en este caso la ciudad y el estado de la dirección son "Nueva York, NY". Afortunadamente, la ciudad de Nueva York publica información vial detallada sobre la Datos abiertos de la ciudad de Nueva York página (CSCL PUB). En segundo lugar, examine el nombre de la calle "Broadway". Ahora sabe que la dirección puede estar en cualquier calle llamada "Broadway" en la ciudad de Nueva York, por lo que puede ejecutar el siguiente código Python para consultar la API SODA de datos abiertos de Nueva York para todas las calles llamadas "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)

 

Hay más de 700 resultados de esta consulta, pero eso no significa que tengas que revisar 700 calles para encontrar tu pizza. Al visualizar los datos, puedes ver que hay 3 calles principales de Broadway y algunas más pequeñas.

 

XXXXX
 

La razón de esto es que cada calle se divide en secciones que corresponden aproximadamente a una cuadra, lo que permite una visión más granular de los datos. El siguiente paso del proceso es determinar exactamente en cuál de estas secciones se encuentra la dirección utilizando el código postal y el número de calle. Cada segmento de calle en el conjunto de datos contiene rangos de direcciones para las direcciones de edificios en los lados izquierdo y derecho de la calle. De manera similar, cada segmento contiene el código postal del lado izquierdo y derecho de la calle. Para ubicar el segmento correcto, el siguiente código aplica filtros para encontrar el segmento de calle cuyo código postal coincide con el código postal de la dirección y cuyo rango de direcciones contiene el número de calle de la dirección.

# 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]

 

Esto reduce la lista al segmento de calle que se ve a continuación.

 

XXXXX
 

La tarea final es determinar dónde se encuentra la dirección en esta línea. Esto se hace colocando el número de la calle dentro del rango de direcciones del segmento, normalizando para determinar qué tan lejos debe estar la dirección en la línea y aplicando esa constante a las coordenadas de los puntos finales de la línea para obtener las coordenadas de la dirección. El siguiente código describe este proceso.

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",
)

 

Una vez terminada la geocodificación de la dirección, ahora es posible trazar la ubicación de esta pizzería en un mapa para comprender su ubicación. Dado que el código anterior analizó información perteneciente al lado izquierdo de un segmento de calle, la ubicación real estará ligeramente a la izquierda del punto trazado en un edificio en el lado izquierdo de la carretera. Finalmente sabes dónde puedes conseguir pizza.

 

XXXXX
 

Este proceso cubre lo que más comúnmente se conoce como geocodificación, pero no es la única forma en que se utiliza el término. También puede ver que la codificación geográfica se refiere al proceso de transferir nombres de puntos de referencia a coordenadas, códigos postales a coordenadas o coordenadas a vectores SIG. Es posible que incluso escuche que se hace referencia a la codificación geográfica inversa (que se tratará más adelante) como codificación geográfica. Una definición más indulgente de codificación geográfica que los abarque sería “la transferencia entre descripciones aproximadas en lenguaje natural de ubicaciones y coordenadas geográficas”. Por lo tanto, cada vez que necesite moverse entre estos dos tipos de datos, considere la codificación geográfica como una solución.

Como alternativa a repetir este proceso cada vez que necesite geocodificar direcciones, se pueden utilizar una variedad de puntos finales de API, como el Geocodificador de la Oficina del Censo de EE. UU. y del API de codificación geográfica de Google, proporciona un servicio de codificación geográfica preciso de forma gratuita. Algunas opciones pagas, como ArcGIS de Esri, Geocodioy Sabelotodo incluso ofrece precisión en el tejado para direcciones seleccionadas, lo que significa que la coordenada devuelta aterriza exactamente en el tejado del edificio en lugar de en una calle cercana. Las siguientes secciones describen cómo utilizar estos servicios para adaptar la codificación geográfica a su canal de datos utilizando el Geocodificador de la Oficina del Censo de EE. UU. como ejemplo.

Para obtener la mayor precisión posible al geocodificar, siempre debe comenzar asegurándose de que sus direcciones tengan el formato que se ajuste a los estándares del servicio elegido. Esto diferirá ligeramente entre cada servicio, pero un formato común es el formato USPS de “PRIMARY# STREET, CITY, STATE, ZIP” donde ESTADO es un código de abreviatura, PRIMARY# es el número de la calle y todas las menciones de números de suite, edificio Se eliminan los números de teléfono y los apartados de correos. 

Una vez que su dirección esté formateada, deberá enviarla a la API para su codificación geográfica. En el caso del Geocodificador de la Oficina del Censo de EE. UU., puede enviar manualmente la dirección a través de la pestaña Procesamiento de direcciones de una línea o usar el API REST proporcionada para enviar la dirección mediante programación. El geocodificador de la Oficina del Censo de EE. UU. también le permite geocodificar archivos completos utilizando el geocodificador por lotes y especificar la fuente de datos utilizando el parámetro de referencia. Para geocodificar la pizzería de antes, este enlace se puede utilizar para pasar la dirección a la API REST, lo que se puede hacer en Python con el siguiente código.

# 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()

 

Los datos devueltos son un archivo JSON, que se decodifica fácilmente en un diccionario de Python. Contiene un campo "tigerLineId" que se puede utilizar para hacer coincidir el archivo de forma de la calle más cercana, un campo "lateral" que se puede utilizar para determinar en qué lado de esa calle se encuentra la dirección y los campos "fromAddress" y "toAddress". que contienen el rango de direcciones para el segmento de calle. Lo más importante es que contiene un campo de "coordenadas" que se puede utilizar para localizar la dirección en un mapa. El siguiente código extrae las coordenadas del archivo JSON y lo procesa en un GeoDataFrame para prepararlo para el análisis espacial.

# 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",
)

 

La visualización de este punto muestra que está ligeramente fuera de la carretera a la izquierda del punto que fue geocodificado manualmente.

 

XXXXX

La geocodificación inversa es el proceso de tomar coordenadas geográficas y hacerlas coincidir con descripciones en lenguaje natural de una región geográfica. Cuando se aplica correctamente, es una de las técnicas más poderosas para adjuntar datos externos al conjunto de herramientas de ciencia de datos. El primer paso de la geocodificación inversa es determinar las zonas geográficas de destino. Esta es la región que contendrá sus datos de coordenadas. Algunos ejemplos comunes son las zonas censales, los códigos postales y las ciudades. El segundo paso es determinar en cuál de esas regiones se encuentra el punto, si es que hay alguna. Cuando se utilizan regiones comunes, el Geocodificador del censo de EE. UU. se puede utilizar para revertir la geocodificación realizando pequeños cambios en la solicitud de API REST. Se vincula una solicitud para determinar qué geografías del Censo contienen la pizzería anterior esta página. El resultado de esta consulta se puede procesar utilizando los mismos métodos que antes. Sin embargo, definir creativamente la región para que se ajuste a una necesidad de análisis y revertir manualmente la geocodificación abre muchas posibilidades. 

Para invertir la geocodificación manualmente, debe determinar la ubicación y la forma de una región y luego determinar si el punto está en el interior de esa región. Determinar si un punto está dentro de un polígono es en realidad un problema bastante difícil, pero el algoritmo de emisión de rayos, donde un rayo que comienza en el punto y viaja infinitamente en una dirección cruza el límite de la región un número impar de veces si está dentro de la región y un número par de veces en caso contrario (Shimrat), se puede usar para resolverlo en la mayoría casos. Para los amantes de las matemáticas, esto es en realidad una aplicación directa de la Teorema de la curva de Jordan (Hosch). Como nota, si está utilizando datos de todo el mundo, el algoritmo de proyección de rayos puede fallar, ya que un rayo eventualmente rodeará la superficie de la Tierra y se convertirá en un círculo. En este caso, deberá encontrar el número de devanado (Weisstein) para la región y el punto. El punto está dentro de la región si el número de devanado no es cero. Afortunadamente, la biblioteca geopandas de Python proporciona la funcionalidad necesaria para definir el interior de una región poligonal y probar si un punto está dentro de ella sin todas las matemáticas complejas.

Si bien la geocodificación manual puede ser demasiado compleja para muchas aplicaciones, la geocodificación inversa manual puede ser una adición práctica a su conjunto de habilidades, ya que le permite hacer coincidir fácilmente sus puntos con regiones altamente personalizadas. Por ejemplo, supongamos que quiere llevar su porción de pizza a un parque y hacer un picnic. Quizás quieras saber si la pizzería se encuentra a poca distancia de un parque. La ciudad de Nueva York proporciona archivos de forma para sus parques como parte del Conjunto de datos de propiedades de parques (Equipo de datos abiertos de parques de la ciudad de Nueva York), y también se puede acceder a ellos a través de su API SODA usando el siguiente código.

# 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", ] )
]

 

Estos parques se pueden agregar a la visualización para ver qué parques están cerca de la pizzería.

 

XXXXX
 

Claramente hay algunas opciones cercanas, pero calcular la distancia usando los archivos de forma y el punto puede ser difícil y costoso desde el punto de vista computacional. En su lugar, se puede aplicar codificación geográfica inversa. El primer paso, como se mencionó anteriormente, es determinar la región a la que desea adjuntar el punto. En este caso, la región está “a media milla de distancia de un parque en la ciudad de Nueva York”. El segundo paso es calcular si el punto se encuentra dentro de una región, lo que se puede hacer matemáticamente usando los métodos mencionados anteriormente o aplicando la función “contiene” en geopandas. El siguiente código se utiliza para agregar una zona de influencia de 1/2 milla a los límites de los parques antes de realizar pruebas para ver qué regiones amortiguadas de los parques ahora contienen el punto.

# 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])]

 

Esta zona de influencia revela los parques cercanos, que están resaltados en azul en la imagen a continuación.

 

XXXXX
 

Después de una geocodificación inversa exitosa, descubrió que hay 8 parques dentro de un radio de media milla de la pizzería en los que podría hacer su picnic. Disfruta esa porción.
 

XXXXX
Rebanada de pizza de j4p4n

Fuentes

  1. Lawler, Josh y Schiess, Peter. ESRM 250: Introducción a los Sistemas de Información Geográfica en Recursos Forestales. Definiciones de SIG, 12 de febrero de 2009, Universidad de Washington, Seattle. Conferencia de clase. https://courses.washington.edu/gis250/lessons/introduction_gis/definitions.html
  2. PUBLICACIÓN CSCL. Datos abiertos de Nueva York. https://data.cityofnewyork.us/City-Government/road/svwp-sbcd
  3. Documentación del geocodificador de la Oficina del Censo de EE. UU. Agosto de 2022. https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf 
  4. Shimrat, M., “Algoritmo 112: Posición del punto relativa al polígono” 1962, Comunicaciones de la ACM Volumen 5, número 8, agosto de 1962. https://dl.acm.org/doi/10.1145/368637.368653 
  5. Hosch, William L.. “Teorema de la curva de Jordan”. Enciclopedia Británica13 de abril de 2018 https://www.britannica.com/science/Jordan-curve-theorem
  6. Weisstein, Eric W. "Número de bobinado de contorno". De mundomatematico–Un recurso web de Wolfram. https://mathworld.wolfram.com/ContourWindingNumber.html
  7. Equipo de datos abiertos de parques de la ciudad de Nueva York. Propiedades de parques. 14 de abril de 2023. https://nycopendata.socrata.com/Recreation/Parks-Properties/enfh-gkve
  8. j4p4n, “Rebanada de pizza”. De OpenClipArt. https://openclipart.org/detail/331718/pizza-slice

 
 
Evan Miller Es miembro de ciencia de datos en Tech Impact, donde utiliza datos para apoyar a agencias gubernamentales y sin fines de lucro con una misión de bien social. Anteriormente, Evan utilizó el aprendizaje automático para entrenar vehículos autónomos en la Universidad Central de Michigan.
 

Sello de tiempo:

Mas de nuggets