Python Panoráma 2: Személyre szabott Google Maps? Készíts saját Webmap-et!11 perc olvasás

Ebben a részben a python alapú webmap-ek világában merülünk el. Manapság, ha térképekről van szó mindenki gondolkozás nélkül pötyögi a “Google” és “Maps” szavakat a böngészőbe. A Google Maps rengeteg célra jól hasznosítható, azonban vannak olyan esetek, amikor egy saját, személyre szabott megoldás mégis sokkal kézenfekvőbb, mint azt elsőként gondolnánk. Bár lehet, hogy az alkalmazásunk nem bír majd, annyi összetett funkcióval, mint a Google Maps vagy más oldalak, viszont a mi applikációnkat teljesen a saját igényeink szerint tudjuk kialakítani. Összességében, mindenképpen érdemes ezt az opciót is fontolóra venni.

CÉL

A mostani részben egy olyan python scriptet fogunk elkészíteni, amelynek az outputja egy .html formátumú térkép lesz, rajta különböző elhelyezkedésű és karakterű térképobjektumokkal. Ebben a cikkben is, az első részhez hasonlóan, először egy Udemy-s Python kurzus (készítette: Ardit Sulce) alappéldáját mutatom be, majd próbáljuk továbbfejleszteni és az üzleti felhasználási lehetőségeit felvázolni.

Elsőként az USA-ban található vulkánok elhelyezkedését és azok tengerszint feletti magasságát szeretnénk ábrázolni egy térképen, majd ezt kibővíteni az egyes országok területére illesztett poligonokkal, amelyek a népesség nagysága alapján egy hőtérkép alkotóelemeként lesznek kiszínezve. Végül pedig megnézzük egy másik lehetséges felhasználását a cikkben bemutatott eszközöknek.

MEGVALÓSÍTÁS

Kezdőlépésként ismét hasznos python könyvtárakkal ismerkedünk meg. Az első könyvtárunk a “folium” lesz, amely lehetőséget nyújt számunkra, hogy magát az alaptérképet felvázoljuk, majd ráillesszünk különböző tulajdonságokkal rendelkező objektumokat, például jelölőket, vonalakat vagy poligonokat, amelyekhez számtalan további funkció rendelhető.

A második importálandó könyvtárunk a “pandas” lesz, ugyanis egy .cvs formátumú fájlban találhatók a vulkánokra vonatkozó adataink és azok kezeléséhez a pandas method-jei szükségesek. Ezek a könyvtárak azonban alapvetően nem találhatók meg a python telepítését követően a modulok között, ezért ezeket le kell töltetnünk a Command Line és a “pip install pandas”, illetve “pip install folium” parancsok segítségével. Ezekután már importálni tudjuk a két könyvtárat a Python scriptünkbe.

Első lépésként készítsük el az alaptérképünket, amelyre majd további objektumokat fogunk tudni elhelyezni. A folium az alaptérképünket egy opensource oldal segítségével képes ábrázolni a folium “Map” methodjének alkalmazásával. Szerencsénkre az argumentumoknak köszönhetően megadható, hogy a térkép pontosan melyik pontját lássa, mekkora zoom érték és térképtípus mellett (sematikus, domborzati, stb.) az a valaki, aki megnyitja a térképünket. Mikor a térképünket ebből az opensource forrásból kinyerjük, akkor érdemes azt egy változóban elmenteni, ugyanis később könnyebben tudunk majd elemeket hozzárendelni és a program végén a térképet elmenteni egy html fájlként.

import folium
import pandas

map = folium.Map(location=[47.497038, 19.056576], zoom_start=7.3, tiles="Mapbox Bright")

map.save("MyMap.html")

Eddig a kódunk arra képes, hogy készítsen egy html fájlt, amely egy adott pontra ugrik és zoom-ol, ha a felhasználó megnyitja a fájlt. Most viszont adjunk hozzá jelölőket is, amelyek az USA-ban található vulkánok pozícióját határozza meg. Ehhez viszont szükségünk lesz a vulkánok helyzetét leíró koordinátákra (szélességi fok, hosszúsági fok). Ezek az adatok rendelkezésünkre állnak a megadott .cvs fájlban, így azokat olvassuk is be a “pandas.read_cvs” method segítségével és tároljuk el egy új változóban.

Ahhoz, hogy jelölőket is hozzá tudjunk adni a térképünkhöz az “add_child” method-öt kell használnunk és azt követően a folium valamelyik jelölőtípusát meghatározó method-jét (a jelölőkről bővebben olvashatsz a “dir(folium)” használatával). Azonban mielőtt még ezeket lelkesedéstől égve gépelnénk be, érdemes a kódunk rendszerezésére is törekedni. Pontosan ezért mindenképpen használjuk a folium FeatureGroup method-jét, hogy a hozzáadott objektumok később könnyebben kezelhetők legyenek. A FeatureGroup csupán egy olyan tároló, amelyhez objektumokat adhatunk hozzá és azt a célt szolgálja, hogy ne közvetlenül a térképhez adjuk hozzá az objektumokat, hanem a FeatureGroup-on keresztül tehessük ezt meg.

Tehát miután elkészítettük a vulkánoknak szánt FeatureGroup-ot, adjuk hozzá a jelölőket a térképhez az add_child method-el. Attól függően, hogy milyen jelölőt választunk, különböző argumentumok értékadására van lehetőségünk. Ezek legtöbbje csupán vizualizációs célt szolgál, viszont mindegyik jelölőtípusnál szükséges megadni annak helyzetét a térképen belül. Ez, a location=[“szélességi fok”, “hosszúsági fok”] argumentum használatával történik, amely egy listaként tartalmazza a két koordinátát .

Ha megnézzük a cvs fájl tartalmát, akkor láthatjuk, hogy a szélességi fok és a hosszúsági fok a két utolsó oszlopot jelenti. Innen igazából két nagyjából hasonló útvonalon indulhatunk el. Az egyik, hogy a pandas könyvtár “iloc” method-jét alkalmazva csak a szükséges oszlopokat vesszük és az így kapott táblázat sorait egy python lista elemeivé alakítjuk. A másik pedig, hogy egyszerűen kikeressük az adattáblából a számunkra jelentősséggel bíró oszlopkat a fejlécen keresztül. Mivel most nincs sok oszlopunk, ezért én inkább a második módszert ajánlom. Tehát akkor a kikeressük a “LAT” és “LON” oszlopkat, azokat listává alakítjuk és eltároljuk egy-egy változóban. Ezekután nincs is másra szükség, minthogy az add_child methodot belerakjuk egy for ciklusba, amely a location argumentumba beírja mindig a soron következő jelölő koordinátáit.

import folium
import pandas

data = pandas.read_csv("Volcanoes_USA.txt")
lat = list(data["LAT"])
lon = list(data["LON"])

map = folium.Map(location=[38.58, -99.09], zoom_start=5, tiles="Mapbox Bright")

fgv = folium.FeatureGroup(name="Volcanoes")

for lt, ln in zip(lat, lon):
fgv.add_child(folium.CircleMarker(location=[lt, ln], radius = 6, popup="Hello! I am a Marker", #color formatting, popup window text etc.
fill_color='green', fill=True, color = 'grey', fill_opacity=0.7))

map.add_child(fgv)

map.save("MyMap.html")

Most, hogy idáig eljutottunk próbáljunk meg poligonokat is a térképünkre illeszteni egy GeoJson fájl segítségével. Ha jobban megnézzük a fájl tartalma nagyon hasonlít egy python szótáréra. Számunkra a fájlból az ország populációjára, illetve a területét lefedő koordinátalistára lesz szükségünk. Szerencsénkre a folium megfelelően tudja kezelni a GeoJson fájlokat, így csupán a megfelelő method-ot és argumentumokat kell alkalmaznunk. Azonban figyelnünk kell, mert a poligonok színét változtatni szeretnénk az alapján, hogy mekkora az ország népessége. Ezt egy soron belüli függvény és if elágazásokkal vitelezhetjük ki. Természetesen ezt is egy FeatureGroup-ba helyezzük és úgy adjuk hozzá a térképünkhöz.

Bár apróságnak tűnik, de valójában nagyon fontos a FeatureGroup-ok hozzáadási sorrendje. Például hogyha jelölőink vannak popup-okkal és mellette poligonjaink és a poligonok adjuk hozzá legutoljára a térképünkhöz, akkor egyszerűen nem fog működni a később hozzáadott jelölők popup-jai. Bár ez részben áthidalható azzal is, ha a térképhez hozzáadunk egy LayerControll panelt.

Ezzel nagyjából el is készültünk az első térképünkkel. Ha szeretnénk még több információt megjeleníteni a vulkánok esetében, akkor még a jelölők színére is definiálhatunk egy magassági szinteket tartalmazó függvényt és a popup-ba is megjeleníthetjük a vulkán magasságát. A kód pedig valahogy így néz ki :

import folium
import pandas

data = pandas.read_csv("Volcanoes_USA.txt")
lat = list(data["LAT"])
lon = list(data["LON"])
elev = list(data["ELEV"])

def color_producer(elevation):
if elevation < 1000:
return 'green'
elif 1000 <= elevation < 3000:
return 'orange'
else:
return 'red'

map = folium.Map(location=[38.58, -99.09], zoom_start=5, tiles="Mapbox Bright")

fgv = folium.FeatureGroup(name="Volcanoes")

for lt, ln, el in zip(lat, lon, elev):
fgv.add_child(folium.CircleMarker(location=[lt, ln], radius = 6, popup=str(el)+" m",
fill_color=color_producer(el), fill=True, color = 'grey', fill_opacity=0.7))

fgp = folium.FeatureGroup(name="Population")

fgp.add_child(folium.GeoJson(data=open("world.json","r",encoding="utf-8-sig").read(),
style_function=lambda x: {"fillColor":"blue" if x["properties"]["POP2005"] < 5000000
else "green" if 5000000 <= x["properties"]["POP2005"] < 30000000 else "red"}))

map.add_child(fgp)
map.add_child(fgv)
map.add_child(folium.LayerControl())

map.save("MyMap.html")

TOVÁBBFEJLESZTÉS ÉS ÜZLETI HASZNOSÍTÁS

Szerintem azért is érdekes és hasznos egy webmap készítés menetének az elsajátítása, mert az emberek áltában vizualizáción keresztül szeretnek tájékozódni. Ahogy az első alkalmazásunknak is sok lehetséges felhasználása adódott, úgy itt is szabadjára kelhet a fantáziánk, hogy miket lehetne ábrázolni, milyen információkkal, milyen vizualizációs elemekkel kiegészítve.

Lehet itt ipari megoldásokra gondolni, például olajfúró tornyok vagy szélerőművek teljesítményéről információt nyújtó alkalmazásokra vagy akár vállalatok stratégiai elemzését alátámasztó vizualizációs eszközre. Az első esetben például vonalak hozzáadásával lehetne továbbfejleszteni a térképet, amelyek a hálózat energiaátadásának hatékonyságáról szolgálnának adatokkal. A második esetben pedig mindenképpen jó lenne az ábra kommunikációs képességén javítani egy komolyabb vizualizációs eszköztáron keresztül.

De akár személyre szabottan is érdemes lehet megpróbálni egy ilyesmi térkép reprodukálását. Aki a térképet a kommunikációs képességét javító irányba szeretné továbbfejlesztni, annak mindenképpen ajánlani tudom BibMartin Jupyter Notebook-ját. Én személy szerint például az egyik egyetemi tárgyamhoz készítettem el a követelményben szereplő városokhoz egy gyakorlótérképet. Ez a térkép, a hozzátartozó kód és a részben használt többi fájl is itt érhető el.

 

Köszönöm, hogy végigolvastad a posztomat és ha érdekesnek találtad, akkor nézz bele a sorozat többi részébe is.

 

Gulácsy Dominik

About Dominik Gulácsy

Sophomore at Corvinus University of Budapest studying International Business who is motivated to use relevant academic knowledge to solve problems through optimisation. Dedicated to fully support the development of new business solutions in close collaboration with team members by IoT and data science applications. Gained experience in SQL and VBA but looking forward to learning more. A keen supporter of the circular economy.

View all posts by Dominik Gulácsy →

Leave a Reply

Your email address will not be published. Required fields are marked *