Jak zmienić adres w współrzędne geograficzne i sprawdzić np. najbliższe restauracje (OpenStreetMap)

OpenStreetMap python

– Tatusiu, co dzisiaj na obiadek? – zapytała Jagódka.

– Hmm… niestety nie zdążyliśmy z mamusią dzisiaj niczego ugotować. Pójdziemy zjeść coś dobrego do pobliskiej restauracji. A na co miałabyś ochotę?

– Mi wszystko jedno. Tylko szybciutko, bo jestem głodna.

– A Ty Otiś co chcesz zjeść?

– Makaron!

– Tatusiu, a jak sprawdzimy, która restauracja jest najbliższa?

– Hmm… możemy szybko nauczyć komputer i sam nam sprawdzi – uśmiechnąłem się.

Bardzo często w wielu danych masz podany adres. Może to być adres klienta do korespondencji, adres kontrahenta lub innej firmy, może to być także adres w opisie samej transakcji kredytowej bądź debetowej.

Budując model szacujący ryzyko kredytowe dla firm (czyli weryfikujący czy dana firma spłaci kredyt), zauważyłem, że dogranie prostej informacji po samym terycie ze spisu powszechnego (informacja o liczbie osób itp.) zwiększył odrobinę moc modelu. Postanowiłem zgłębić temat! Pomyślałem, że w przypadku niektórych firm ciekawą informacją byłaby odległość do najbliższej restauracji (np. konkurencja), pola (czy tereny wiejskie) lub fontanny (np. centrum miasta 😊).

Też chcesz nauczyć się zamienić adres na charakterystyki? To zaczynamy!

Co to jest OpenStreetMap?

OpenStreetMap (skrótowo OSM) to globalny projekt mający na celu stworzenie darmowej oraz powszechnie dostępnej mapy świata. Jest to niejako kartograficzny odpowiednik Wikipedii. Może być używana i edytowana przez każdego!

Dane zawarte w projekcie udostępniane są na otwartej licencji ODbL. Dzięki temu istnieje możliwość wykorzystywania danych we własnych projektach, co czyni ją darmową alternatywą dla drogich, niekoniecznie lepszych, map komercyjnych.

Sam projekt, zainicjowany w 2004 roku, tworzy obecnie ponad 350 tysięcy mapowiczów (tak nazywają siebie zarejestrowani użytkownicy edytujący OSM), a wszystkie przesłane obiekty „ważą” ponad 200 gigabajtów.

OpenStreetMap
https://www.openstreetmap.org/

Czym są współrzędne geograficzne?

Współrzędne geograficzne są punktami określającymi położenie punktu na powierzchni naszej planety. Mierzone są w stopniach, minutach i sekundach kątowych. Składają się z dwóch punktów:

  • szerokość (ang. latitude),
  • długości (ang. lenght).

Początkiem układu współrzędnych geograficznych jest przecięcie się południka zerowego (Greenwich) z równikiem. Przyjęto zapisywać najpierw szerokość (północ-południe), a następnie długość geograficzną (wschód-zachód).

współrzędne geograficzne

Jak policzyć odległość między dwoma punktami?

Można podejść do tego na kilka sposobów.

1. Prosto

Jeśli chcemy policzyć odległość między dwoma punktami, to może nam wystarczyć prosta odległość euklidesowa.

2. Bardziej matematycznie

Świat nie jest płaski (jeśli jesteś płaskoziemcem to przepraszam Cię za moją opinię), tylko jest kulą.

Dlatego chcąc policzyć dokładną odległość nie można przyjąć prostej metryki euklidesowej. Można zastosować np. formułę Haversine’a.

A oto wzór:

wzór formuła haversine'a

Nie bój się – nie musisz nic liczyć tylko wystarczy wczytać funkcję!

Nominatim – co to jest?

Nominatim to narzędzie do wyszukiwania danych OpenSteetMap (OSM) według nazwy i adresu (geokodowanie). Można go znaleźć pod adresem https://nominatim.openstreetmap.org/

Za pośrednictwem interfejsu API można w prosty sposób odpytywać o dane punkty z OpenStreetMap. Możesz szukać nazwy lub adresu (wyszukiwanie do przodu) lub wyszukiwać dane według ich współrzędnych geograficznych (wyszukiwanie do tyłu). Każdy wynik zawiera łącze do strony ze szczegółami, gdzie można sprawdzić, jakie dane o obiekcie są zapisane w bazie danych.

Zaraz go wykorzystamy!

OpenStreetMap & Nominatim

Jak znaleźć współrzędne geograficzne mając adres?

Tak jak się domyślasz – wszystko w Python jest już zaimplementowane i wystarczy tylko tego użyć!

Wczytajmy nasz geolokator (narzędzie pozwalające zmienić adres na współrzędne i w drugą stronę) podając jakąś nazwę użytkownika.

from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="miroslawmamczur.pl")

Uwaga. Pamiętaj, aby przeczytać regulamin, żeby prawidłowo użytkować Nominatim (np. nie wysyłać zbyt wielu zapytań w ciągu sekundy)!

adress = 'Wrocław Rynek 9/11'
location = geolocator.geocode(adress)
location
OpenStreetMap zmiana adresu na współrzędne geograficzne python

Funkcja geocode ma szereg ciekawych parametrów takich jak:

  • query (string) – zapytanie lub ustrukturyzowany adres. Pamiętajmy, że kluczem jest ulica, miasto, województwo, państwo lub kod pocztowy.
  • exactly_one (bool) – domyślnie zwraca tylko jeden adres. Można to zmienić jeśli jest ich więcej. 
  • timeout (int) – czas, który dajemy na odpowiedź, zanim wywołamy błąd.
  • limit (int) – maksymalna wartość odpowiedzi, jaką otrzymamy z Nominatim.
  • addressdetails (bool) – warto dać jako True, jeśli interesują nas szczegóły adresu takie jak osiedle, dzielnica itp.
  • extratags (bool) – dzięki temu dostaniemy wszelkie dodatkowe informacje, np. linki do stron, godziny otwarcia.
  • viewbox – możliwość zawężenia szukania do konkretnego prostokąta. Podajemy jako listę dwóch punktów (latitude, longitude) 

W dokumentacji możesz przeczytać o większej liczbie parametrów i dowiedzieć się więcej o ich działaniu.

location = geolocator.geocode(query=adress, exactly_one=True, 
                              addressdetails=True, extratags=True)
location
OpenStreetMap zmiana adresu na współrzędne geograficzne python

Ciekawostka! Nie musimy wykorzystywać biblioteki geopy. Pamiętajmy, że Nominatim to serwer, z którym można się połączyć! Zatem odpowiednio tworząc zapytanie otrzymamy odpowiedź w formacie json. Sprawdźcie ten LINK – zwrotka z informacją co znajduje się we Wrocławiu pod numerem Rynek 9/11. Okazuje się, że na OpenStreetMap mamy aż 3 obiekty: budynek, Santander (firma) oraz bankomat.

import requests

link = "https://nominatim.openstreetmap.org/?addressdetails=1&q=Wroc%C5%82aw+Rynek+9/11&format=json&extratags=1"

answer = requests.get(link).json()
answer[2]
OpenStreetMap zmiana adresu na współrzędne geograficzne python

Spójrz ile informacji otrzymujemy! Dla przykładu wyświetliłem tylko informacje o bankomacie (atm). Widzimy nazwę operatora, godziny otwarcia, czy może podjechać osoba na wózku inwalidzkim. Dodatkowo mamy nawet boudingbox – czyli prostokąt na mapce gdzie jest!

A w drugą stronę? Mając współrzędne geograficzne jak otrzymać adres?

Wystarczy chwilka w dokumentacji i już mamy odwrotną funkcję reverse!

lat_long = (51.1098784, 17.0301279, 0.0)
location = geolocator.reverse(query=lat_long, exactly_one=True, addressdetails=True)
location
nominatim zamiana współrzędnych geograficznych w adres python

A jak znaleźć najbliższą restaurację lub szkołę na mapie OpenStreetMap?

Przyznam, że nie było łatwo. Znalazłem kilka pakietów, które miały w tym pomagać. Jednak nie miały najnowszych wersji i miałem problemy z instalacjami. Na szczęście pomógł mi szefo Przemek. Okazało się, że wystarczy drobna modyfikacja tego, co zrobiliśmy do tej pory. Aby znaleźć okoliczne restauracje, wystarczy w składni zapytania dopisać odpowiedni TAG przed adresem i dodać near.

Wygląda to tak:

location = geolocator.geocode(query='restaurant near '+adress, 
                              exactly_one=False, limit = 5)
location
NOminatim OpenStreetMap wyszukanie w pobliżu adresu reastauracji

Warto dodać, że można wyszukać mnóstwo punktów – więzienia, kluby nocne, hydranty, puby itd. Pełną listę znajdziecie pod tym adresem https://wiki.openstreetmap.org/wiki/Nominatim/Special_Phrases/PL

Chwilkę zabawy i można zrobić prostą funkcję, która dla każdego adresu i tag’a zwróci listę top N lokalizacji z dokładnymi odległościami wyrażonymi w kilometrach.

from geopy.geocoders import Nominatim
from geopy.distance import geodesic

import pandas as pd

geolocator = Nominatim(user_agent="miroslawmamczur.pl")

def geo_near(adress, tag, limit=10):
    # zdefiniowanie dataframe
    df = pd.DataFrame(columns = ['Name', 'distance'])
    # geolokalizacja adresu
    location = geolocator.geocode(adress, exactly_one=False)
    # geo najbliższych rzeczy oznaczonych w OSM jako tags
    location_near = geolocator.geocode(tag+' near ' + adress, 
                                       exactly_one=False,
                                       addressdetails=True, 
                                       extratags=True, 
                                       limit=limit)

    if location_near is None:
        print('Nic nie znalazłem :(')
    else:
        for i in range(len(location_near)):
            df.loc[i] = [location_near[i][0].split(',', 1)[0],
                         round(geodesic(location[0][1], 
                                        location_near[i][1]).km,2)]
            
    return df.sort_values(by='distance').reset_index(drop=True)

adress = 'Wrocław robotnicza 11'
tag = 'school'

geo_near(adress, tag)
Nominatim python wyszukanie najbliższych szkół restauracji (OpenStreetMap)

Overpass API

Potrzebujesz pobrać od razu wszystkie szkoły lub restauracje w Polsce? Nie ma problemu!

Możesz wykorzystać API overpass, które umożliwia wyciągnięcie wszystkich informacji z OpenStreetMap 😊 Więcej możesz znaleźć na przykład TUTAJ.

Duże zbiory danych (ściągnij OpenStreetMap)

Potrzebujesz jeszcze więcej mapy? Pewnie nie zaskoczę Cię – to również możliwe 😊 Wystarczy pobrać wszystkie dane, które są w OpenStreetMap! Możesz na przykład skorzystać ze strony Geofabrik (https://download.geofabrik.de/ ) .

Ten serwer zawiera wyciągi danych z projektu OpenStreetMap, które są zwykle aktualizowane codziennie. Wystarczy wybrać odpowiedni kontynent i pobrać dane. Jeśli chciałbyś wyliczyć charakterystyki dla milionów miejsc to na pewno polecałbym to rozwiązanie.

Potencjał nowych danych!

A po co to wszystko? Głównie po to, aby pokazać Ci, jak na podstawie adresu można wyciągnąć dodatkowe informacje. Porozmawiaj z ekspertami domenowymi na temat problemu, który rozwiązujesz, czy jeśli masz adres to widzą oni jakieś ciekawe cechy. Może jeśli budujesz model, czy warto w danym miejscu otworzyć restauracje dodasz do niego cechę liczba knajp w okolicy? Albo najbliższa odległość do bankomatu? Dzięki informacjom z tego artykułu już umiesz to zrobić!

A dodatkowo jeśli chcesz zwizualizować swoje wyniki, możesz skorzystać, chociażby z pakietu folium – przykład na blogu TUTAJ.

Pozdrawiam serdecznie,

podpis Mirek

Image by MichaelGaida from Pixabay

.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *