Геокодування для дослідників даних - KDnuggets

Геокодування для дослідників даних – KDnuggets

Вихідний вузол: 2713218

Коли дослідникам даних потрібно знати все про те, «де» їхні дані, вони часто звертаються до геоінформаційних систем (ГІС). ГІС — це складний набір технологій і програм, які служать різноманітним цілям, але Університет Вашингтона дає досить повне визначення, кажучи, що «географічна інформаційна система — це складна система асоційованих або пов’язаних речей або об’єктів, метою яких є передавати знання про особливості поверхні землі» (Lawler et al). ГІС охоплює широкий спектр методів обробки просторових даних від отримання до візуалізації, багато з яких є цінними інструментами, навіть якщо ви не є спеціалістом з ГІС. Ця стаття містить вичерпний огляд геокодування з демонстрацією кількох практичних застосувань на Python. Зокрема, ви визначите точне розташування піцерії в Нью-Йорку, Нью-Йорк, використовуючи її адресу та пов’яжете її з даними про найближчі парки. Хоча в демонстраціях використовується код Python, основні концепції можна застосувати до багатьох середовищ програмування, щоб інтегрувати геокодування у ваш робочий процес. Ці інструменти створюють основу для перетворення даних у просторові та відкривають двері для складнішого географічного аналізу. 

 

XXXXX

Геокодування найчастіше визначається як перетворення адресних даних у картографічні координати. Зазвичай це передбачає виявлення назви вулиці в адресі, зіставлення цієї вулиці з межами її реального аналога в базі даних, а потім оцінку місця на вулиці, щоб розмістити адресу за допомогою номера вулиці. Як приклад, розглянемо процес простого ручного геокодування для адреси піцерії в Нью-Йорку на Бродвеї: 2709 Broadway, New York, NY 10025. Перше завдання — знайти відповідні шейп-файли для дорожньої системи місця розташування вашої адреси. Зверніть увагу, що в цьому випадку місто та штат адреси «Нью-Йорк, Нью-Йорк». На щастя, місто Нью-Йорк публікує детальну інформацію про дороги Відкриті дані NYC сторінка (CSCL PUB). По-друге, розгляньте назву вулиці «Бродвей». Тепер ви знаєте, що адреса може лежати на будь-якій вулиці під назвою «Бродвей» у місті Нью-Йорк, тому ви можете виконати наведений нижче код Python, щоб запитати NYC Open Data SODA API для всіх вулиць під назвою «Бродвей».

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)

 

Існує понад 700 результатів цього запиту, але це не означає, що вам потрібно перевірити 700 вулиць, щоб знайти свою піцу. Візуалізувавши дані, ви можете побачити, що є 3 головні вулиці Бродвею та кілька менших.

 

XXXXX
 

Причина цього полягає в тому, що кожна вулиця розбита на ділянки, які приблизно відповідають кварталу, що дозволяє більш детально переглядати дані. Наступним кроком процесу є визначення точного з цих розділів адреси за допомогою поштового індексу та номера вулиці. Кожен сегмент вулиці в наборі даних містить діапазони адрес для адрес будинків ліворуч і праворуч від вулиці. Так само кожен сегмент містить поштовий індекс для лівої та правої сторони вулиці. Щоб знайти правильний сегмент, наступний код застосовує фільтри, щоб знайти сегмент вулиці, поштовий індекс якого відповідає поштовому індексу адреси, а діапазон адрес містить номер вулиці адреси.

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

 

Це звузить список до одного сегмента вулиці, показаного нижче.

 

XXXXX
 

Останнє завдання — визначити, де в цьому рядку знаходиться адреса. Це робиться шляхом розміщення номера вулиці в діапазоні адрес для сегмента, нормалізації, щоб визначити, наскільки далеко вздовж лінії має бути адреса, і застосування цієї константи до координат кінцевих точок лінії, щоб отримати координати адреси. Наступний код описує цей процес.

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

 

Після завершення геокодування адреси тепер можна нанести на карту розташування цієї піцерії, щоб зрозуміти її розташування. Оскільки код вище розглядав інформацію, що стосується лівого боку сегмента вулиці, фактичне розташування буде трохи лівіше нанесеної точки в будівлі з лівого боку дороги. Ви нарешті знаєте, де можна взяти піцу.

 

XXXXX
 

Цей процес охоплює те, що найчастіше називають геокодуванням, але це не єдиний спосіб використання цього терміну. Ви також можете бачити, що геокодування стосується процесу перенесення назв орієнтирів у координати, поштових індексів у координати або координат у вектори ГІС. Ви навіть можете почути зворотне геокодування (про яке ми розглянемо пізніше), яке називають геокодуванням. Більш м’яким визначенням геокодування, яке охоплює це, було б «перехід між приблизними описами місцевостей природною мовою та географічними координатами». Тому щоразу, коли вам потрібно переходити між цими двома типами даних, розгляньте геокодування як рішення.

Як альтернатива повторенню цього процесу щоразу, коли вам потрібно геокодувати адреси, різні кінцеві точки API, такі як Геокодер Бюро перепису населення США і API геокодування Google, безкоштовно надають точні послуги геокодування. Деякі платні варіанти, наприклад ArcGIS від Esri, Geocodio та Всезнайка навіть пропонують точність на даху для вибраних адрес, що означає, що повернута координата потрапляє точно на дах будівлі, а не на сусідню вулицю. У наступних розділах описано, як використовувати ці служби, щоб вставити геокодування у ваш канал даних, використовуючи Geocoder Бюро перепису США як приклад.

Щоб отримати найвищу можливу точність під час геокодування, вам завжди слід починати з того, щоб ваші адреси відформатовано відповідно до стандартів вибраної вами служби. Це дещо відрізнятиметься для кожної служби, але загальним форматом є формат USPS «PRIMARY# STREET, CITY, STATE, ZIP», де STATE — це абревіатура, PRIMARY# — це номер вулиці, а всі згадки про номери квартир, будівель номери та поштові скриньки видаляються. 

Після того, як ваша адреса відформатована, її потрібно надіслати в API для геокодування. У випадку з геокодувальником Бюро перепису населення США ви можете вручну надіслати адресу на вкладці «Обробка однорядкової адреси» або скористатися наданий REST API подати адресу програмно. Геокодер Бюро перепису населення США також дозволяє геокодувати цілі файли за допомогою пакетного геокодера та вказувати джерело даних за допомогою параметра порівняння. Щоб геокодувати піцерію раніше, посилання можна використовувати для передачі адреси в REST API, що можна зробити в Python за допомогою наступного коду.

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

 

Повернуті дані є файлом JSON, який легко декодується у словник Python. Він містить поле «tigerLineId», яке можна використовувати, щоб зіставити шейп-файл для найближчої вулиці, поле «side», яке можна використовувати, щоб визначити, на якій стороні вулиці знаходиться адреса, а також поля «fromAddress» і «toAddress». які містять діапазон адрес для сегмента вулиці. Найважливіше те, що він містить поле «координати», за допомогою якого можна знайти адресу на карті. Наступний код витягує координати з файлу JSON і обробляє їх у GeoDataFrame для підготовки до просторового аналізу.

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

 

Візуалізація цієї точки показує, що вона трохи осторонь дороги ліворуч від точки, геокодованої вручну.

 

XXXXX

Зворотне геокодування — це процес отримання географічних координат і зіставлення їх із описом природної мови географічного регіону. При правильному застосуванні це один із найпотужніших методів додавання зовнішніх даних у інструментарій обробки даних. Першим кроком зворотного геокодування є визначення вашої цільової географії. Це область, яка міститиме ваші координати. Деякими типовими прикладами є переписні ділянки, поштові індекси та міста. Другим кроком є ​​визначення того, в якому з цих регіонів знаходиться точка, якщо такі є. При використанні загальних регіонів Геокодер перепису населення США можна використовувати для зворотного геокодування, вносячи невеликі зміни в запит REST API. Запит на визначення географічних регіонів перепису містить піцерію раніше, пов’язано тут. Результат цього запиту можна обробити за допомогою тих же методів, що й раніше. Однак креативне визначення регіону відповідно до потреб аналізу та зворотне геокодування вручну відкриває багато можливостей. 

Щоб змінити геокодування вручну, вам потрібно визначити розташування та форму регіону, а потім визначити, чи знаходиться точка всередині цього регіону. Визначити, чи знаходиться точка всередині багатокутника, насправді є досить складною проблемою, але алгоритм кастингу променів, де промінь, що починається в точці та рухається нескінченно в певному напрямку, перетинає межу регіону непарну кількість разів, якщо він знаходиться всередині регіону, і парну кількість разів в іншому випадку (Шімрат), можна використовувати для розв’язання у більшості випадків. Для тих, хто схильний до математики, це фактично пряме застосування Теорема жорданової кривої (Гош). Зауважте, що якщо ви використовуєте дані з усього світу, алгоритм відкидання променів може фактично дати збій, оскільки промінь з часом огорнеться навколо поверхні Землі та стане колом. У цьому випадку замість цього вам доведеться знайти число намотування (Вайштейна) для регіону та точки. Точка знаходиться всередині області, якщо число намотування не дорівнює нулю. На щастя, бібліотека geopandas Python надає функціональні можливості, необхідні як для визначення внутрішньої частини багатокутної області, так і для перевірки того, чи є точка всередині неї, без усієї складної математики.

Хоча ручне геокодування може бути надто складним для багатьох застосувань, ручне зворотне геокодування може стати практичним доповненням до вашого набору навичок, оскільки воно дає змогу легко зіставляти ваші точки з дуже налаштованими регіонами. Наприклад, припустімо, що ви хочете взяти свій шматочок піци в парк і влаштувати пікнік. Можливо, ви захочете знати, чи знаходиться піцерія на короткій відстані від парку. Нью-Йорк надає шейп-файли для своїх парків як частину Набір даних Parks Properties (Команда відкритих даних парків Нью-Йорка), і до них також можна отримати доступ через їх SODA API за допомогою наступного коду.

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

 

Ці парки можна додати до візуалізації, щоб побачити, які парки знаходяться поблизу піцерії.

 

XXXXX
 

Очевидно, що поблизу є кілька варіантів, але визначення відстані за допомогою шейп-файлів і точки може бути складним і дорогим за обчисленням. Замість цього можна застосувати зворотне геокодування. Першим кроком, як згадувалося вище, є визначення регіону, до якого потрібно приєднати точку. У цьому випадку регіон знаходиться «на відстані 1/2 милі від парку в Нью-Йорку». Другим кроком є ​​обчислення, якщо точка лежить всередині регіону, що можна зробити математично за допомогою раніше згаданих методів або застосувавши функцію «contains» у geopandas. Наступний код використовується для додавання буфера 1/2 милі до меж парків перед тестуванням, щоб побачити, які буферні регіони парків тепер містять цю точку.

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

 

Цей буфер показує найближчі парки, які виділено синім кольором на зображенні нижче

 

XXXXX
 

Після успішного зворотного геокодування ви дізналися, що в радіусі півмилі від піцерії є 8 парків, у яких можна влаштувати пікнік. Насолоджуйтесь цим шматочком.
 

XXXXX
Pizza Slice від j4p4n

Джерела

  1. Лоулер, Джош і Шисс, Пітер. ESRM 250: Вступ до геоінформаційних систем у лісових ресурсах. Визначення ГІС, 12 лютого 2009 р., Вашингтонський університет, Сіетл. Класна лекція. https://courses.washington.edu/gis250/lessons/introduction_gis/definitions.html
  2. CSCL PUB. Нью-Йорк OpenData. https://data.cityofnewyork.us/City-Government/road/svwp-sbcd
  3. Документація геокодера Бюро перепису населення США. серпень 2022 р. https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf 
  4. Шімрат, М., «Алгоритм 112: Положення точки відносно багатокутника» 1962, Зв'язок ОСББ Том 5, випуск 8, серпень 1962 р. https://dl.acm.org/doi/10.1145/368637.368653 
  5. Хош, Вільям Л. «Теорема кривої Джордана». Енциклопедія Британіка, 13 квітня 2018 р., https://www.britannica.com/science/Jordan-curve-theorem
  6. Вайштайн, Ерік В. «Номер намотування контуру». Від MathWorld– Веб-ресурс Wolfram. https://mathworld.wolfram.com/ContourWindingNumber.html
  7. Команда відкритих даних NYC Parks. Власності парків. 14 квітня 2023 р. https://nycopendata.socrata.com/Recreation/Parks-Properties/enfh-gkve
  8. j4p4n, «Шматочок піци». Від OpenClipArt. https://openclipart.org/detail/331718/pizza-slice

 
 
Еван Міллер є науковим співробітником Data Science в Tech Impact, де він використовує дані для підтримки некомерційних і державних установ із місією соціального блага. Раніше Еван використовував машинне навчання для навчання автономних транспортних засобів у Центральному Мічиганському університеті.
 

Часова мітка:

Більше від KDnuggets