{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#
Térképes, geolokációs adatok felhasználása
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Háttér\n", "\n", "A térképes, geolokációs adatok felhasználása ma már az adatelemzési repertoár magától értetődő része.\n", "\n", "Minden jelentősebb vizualizációs szoftver képes térképes adatok megjelenítésére, e tekintetben tehát remek a helyzet. Előfordulhat ugyan, hogy nem vagyunk kibékülve az alapbeállításként használt Google Maps, OpenStreetMap, vagy Bing Maps egyik-másik tulajdonságával, komoly fejfájást azonban nem fognak okozni." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A sült galamb nem repül a szánkba\n", "\n", "A megjelenítéshez azonban **elő kell készíteni** a térképes adatokat, s a rendelkezésre álló adatszetten túl **gyakran kell (kéne) külső forrásból kiegészítő információkat beszereznünk**. Erre mutatok három példát, megvalósításukkal együtt:\n", "1. valós címek földrajzi koordinátákká alakítása\n", "2. földrajzi pontok közötti távolság légvonalban\n", "3. földrajzi pontok közötti távolság közúton" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Az illusztráció által használt technológia\n", "\n", "Python 3.6 szoftverkörnyezetben, az Anaconda csomag, és +1 letölthető csomag használatával mutatok be egy egyszerűbb megoldást. A Google térképszolgáltatásának, a Google Maps-nek a programozási interface-ét (API-ját) is használni fogom.\n", "\n", "A teljes kód letölthető Jupyter Notebook (korábbi nevén: IPython Notebook) formátumban." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Adatkör\n", "\n", "Tegyük föl, hogy különböző magyar városok polgármesteri hivatalainak címe áll rendelkezésre, szépen, rendezett formában, egy Excel-fájlban." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import haversine # légvonalban mért földrajzi távolság\n", "import numpy as np\n", "import pandas as pd\n", "import requests # HTTP lekérdezések, ezt használjuk a Google Maps API-k eléréséhez\n", "import time # késleltetés\n", "import xlsxwriter # mentés Excel fájlba" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pd.set_option(\"display.max_rows\", 12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beolvasom Excelből a címeket, és a Python Pandas csomagjának DataFrame objektumában (egyfajta speciális táblázatban) tárolom." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MegyeIrányítószámVárosKözterület
0Csongrád6720SzegedSzéchenyi tér 10.
1Hajdú-Bihar4024DebrecenPiac u. 20.
2Budapest1052BudapestVárosház u. 9-11.
3Bács-Kiskun6000KecskemétKossuth tér 1.
\n", "
" ], "text/plain": [ " Megye Irányítószám Város Közterület\n", "0 Csongrád 6720 Szeged Széchenyi tér 10.\n", "1 Hajdú-Bihar 4024 Debrecen Piac u. 20.\n", "2 Budapest 1052 Budapest Városház u. 9-11.\n", "3 Bács-Kiskun 6000 Kecskemét Kossuth tér 1." ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_excel(\"Városháza.xlsx\")\n", "df.head() # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1) Címek átalakítása földrajzi koordinátákká\n", "\n", "Első feladatként alakítsuk a címeket pontos földrajzi koordinátákká! A _**Google Maps Geocoding API**_ felhasználásával egyszerűen meg tudjuk tenni, legalábbis ha nem túl sok címről van szó.\n", "\n", "A felhasználási kvóta (most) **napi 2500 lekérdezés** – fejlesztési fázisban érdemes tehát a teljes adatkörnek csupán egy szeletén próbálkozni, s majd csak a kész verzióban lekérdezni az összes szükséges címet. API „kulcsot” igényelni [ezen a címen lehet](https://developers.google.com/maps/documentation/geocoding/get-api-key), ezt minden lekérdezésbe bele kell építeni (lásd a forráskódban).\n", "\n", "A Google védekezik szervereinek túlterhelése ellen, ezért **kisebb várakozást is érdemes beiktatni** az egyes lekérdezések közé. 3 másodperc elég lehet, így persze lassulnak a lekérdezések, lehet tehát próbálkozni, és feszegetni a határokat :)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# konstansok, amit használni fogunk (Python nyelvben valódi konstansok híján: később szándékosan meg nem változtatott változók)\n", "\n", "# Google Maps API kulcsok, például itt lehet igényelni: https://developers.google.com/maps/documentation/geocoding/get-api-key\n", "CONST_GEOCODE_API_KEY = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\" # ez most __használhatatlan__, szándékosan hamis kulcs ;)\n", "CONST_DISTANCE_API_KEY = CONST_GEOCODE_API_KEY\n", "\n", "# pontosító jellegű kiegészítések\n", "CONST_ORSZAG = \"Magyarország\" # minden adatpont ebben az országban van\n", "CONST_REGIO = \"hu\" # pontosító régió; még véletlenül sem az USA-ban található Budapest településre vagyunk kíváncsiak, hanem az itthonira :)\n", "\n", "# várakozási idők két lekérdezés között (másodpercben)\n", "CONST_SLEEP_GEOCODE_KOZOTT = 3\n", "CONST_SLEEP_DISTANCEMATRIX_KOZOTT = 11\n", "CONST_SLEEP_ERROR_KEZDETI = 15\n", "CONST_SLEEP_ERROR_MAXIMUM = 30" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Létrehozok új oszlopokat, ahol a földrajzi koordinátákat írom majd. Az ilyen típusú adatoknak hagyományosan kétféle leképezése ismert:\n", "- historikus, fok-perc-másodperc formátum, ahol Budapest: 47°30’ északi szélesség, 19°03’ keleti hosszúság\n", "- tizedes törtszám, ahol Budapest: 47,5 északi szélesség, 19,05 keleti hosszúság\n", "\n", "Most a **tizedes törtszám leképezést** fogom használni." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# két új oszlop a koordináták komponenseinek\n", "for oszlop in [\"geo_szelesseg\", \"geo_hosszusag\"]:\n", " df[oszlop] = None\n", " df[oszlop] = df[oszlop].astype(float) # tizedes tört adattípus" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 4 entries, 0 to 3\n", "Data columns (total 6 columns):\n", "Megye 4 non-null object\n", "Irányítószám 4 non-null int64\n", "Város 4 non-null object\n", "Közterület 4 non-null object\n", "geo_szelesseg 0 non-null float64\n", "geo_hosszusag 0 non-null float64\n", "dtypes: float64(2), int64(1), object(3)\n", "memory usage: 272.0+ bytes\n" ] } ], "source": [ "df.info() # áttekintés; a DataFrame oszlopai és adattípusai" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MegyeIrányítószámVárosKözterületgeo_szelesseggeo_hosszusag
0Csongrád6720SzegedSzéchenyi tér 10.NaNNaN
1Hajdú-Bihar4024DebrecenPiac u. 20.NaNNaN
2Budapest1052BudapestVárosház u. 9-11.NaNNaN
3Bács-Kiskun6000KecskemétKossuth tér 1.NaNNaN
\n", "
" ], "text/plain": [ " Megye Irányítószám Város Közterület geo_szelesseg \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. NaN \n", "1 Hajdú-Bihar 4024 Debrecen Piac u. 20. NaN \n", "2 Budapest 1052 Budapest Városház u. 9-11. NaN \n", "3 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. NaN \n", "\n", " geo_hosszusag \n", "0 NaN \n", "1 NaN \n", "2 NaN \n", "3 NaN " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head() # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Google Maps Geocoding API **lekérdezését ketté bontom**:\n", "- egyrészt össze kell állítani az API felé elküldött lekérdezést\n", "- másrészt föl kell dolgozni a Google válaszát.\n", "\n", "Lássuk a két kódot, mégpedig fordított sorrendben." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Google válaszát annak szabványos struktúrája szerint dolgozom föl. JSON formátumban kérjem le a Google-től, amit Python dictionary típusként egyszerű tovább alakítani.\n", "\n", "Több okból **előfrodulhat, hogy a Google szerverétől nem érkezik rendes válasz**:\n", "- megszakadt az internet-kapcsolat\n", "- túlléptem a Google-nél a lekérdezések napi limitjét\n", "- érvénytelen formátumban indítottam a lekérést\n", "- stb.\n", "\n", "Bizonyos esetekben érdemes változatlan formátumban újra (és újra, és újra...) lekérdezni; például ismeretlen hiba, nosza, várjunk egy keveset és próbáljuk újra! Más esetekben fölösleges várnunk (érvénytelen formátumban indított lekérést fölösleges megismételni)." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def geocode_query(webcim, varakozas=CONST_SLEEP_ERROR_KEZDETI, max_varakozas=CONST_SLEEP_ERROR_MAXIMUM):\n", " \"\"\"A Google Maps Geocoding API felé indított lekérdezések végrehajtása. Az eredmény Python dictionary (kulcs-érték szótár) típusú.\"\"\"\n", " rj = requests.get(webcim).json() # lekérdezést indítunk, és az eredményt JSON formátummá alakítjuk\n", " if rj.get(\"status\") == \"OK\" and len(rj.get(\"results\", [])) > 0: # a Google Maps Geocoding API mondjuk elvileg akkor is visszaad egy üres \"results\" tömböt, ha nincs találat, de azért így a biztos...\n", " # Itt persze lenne tér némi barkácsolásra, például hogy ne fixen a Google által fölkínált\n", " # legelső lehetőséget használjuk (Pythonban: 0 indexű találat, rj[\"results\"][0]),\n", " # hanem egy másikat, esetleg többet is. Hiányos, zavaros, irányítószám nélküli címeknél\n", " # lehet több eredményünk... Az egyszerűség kedvéért most csak a legelső szerepel.\n", " return {\"lat\": rj[\"results\"][0][\"geometry\"][\"location\"][\"lat\"],\n", " \"lng\": rj[\"results\"][0][\"geometry\"][\"location\"][\"lng\"],\n", " \"status_ok\": 1} # remek, valódi eredményünk van\n", " elif rj.get(\"status\") == \"UNKNOWN_ERROR\" or rj.get(\"status\") is None:\n", " if varakozas > max_varakozas:\n", " return {\"lat\": 0,\n", " \"lng\": 0,\n", " \"status_ok\": 0} # majd később kiszűrjük őket\n", " else:\n", " time.sleep(varakozas) # várakozunk\n", " return geocode_query(webcim, varakozas*2) # növeljük a várakozási időt, s újra nekifutunk\n", " else:\n", " return {\"lat\": 0,\n", " \"lng\": 0,\n", " \"status_ok\": 0} # majd később kiszűrjük őket, és \"INVALID_REQUEST\", \"MAX_ELEMENTS_EXCEEDED\", \"OVER_QUERY_LIMIT\", \"REQUEST_DENIED\" esetén egyáltalán nem futunk neki ismét" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Google Maps Geocoding API felé indított lekérdezésnél maradhatnak pl. a magyar ékezetes karakterek az utcanevekben, semmi szükség őket átalakítani, a szóközöket azonban „+” jelre cserélem. Régiót, esetleg konkrét országot is megadok szűkítésként (van „Buda” az USA Texas államában is, például).\n", "\n", "Paraméter, hogy **az adott DataFrame hányadik oszlopában szerepel az irányítószám, a város, a cím**, továbbá hogy a DataFrame **hányadik oszlopában kell visszaadnom a földrajzi szélesség és hosszúság koordinátáit**." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def geocode_dataframe(p, cim_oszlopok=(0, 1, 2), geo_oszlopok=(3, 4)):\n", " \"\"\"A Google Maps Geocoding API felé indított lekérdezés összeállítása, és az eredmények tárolása.\"\"\"\n", " \n", " \"\"\"cim_oszlopok: irányítószám, város, városon belüli cím sorrendben kell a paraméter tuple-t érteni\n", " geo_oszlopok: előbb a földrajzi szélesség, majd a földrajzi hosszúság oszlopa szerepel a tuple-ben\"\"\"\n", " \n", " i = 0\n", " while i < len(p):\n", " lnk = \"https://maps.googleapis.com/maps/api/geocode/json?address={varos}+{cim}+{irsz}+{orszag}®ion={region}&key={api_key}\".format( \\\n", " cim = p.iloc[i, cim_oszlopok[2]].replace(\" \", \"+\").strip(), \\\n", " varos = p.iloc[i, cim_oszlopok[1]].replace(\" \", \"+\").strip(), \\\n", " irsz = str(p.iloc[i, cim_oszlopok[0]]), \\\n", " orszag = CONST_ORSZAG, \\\n", " region = CONST_REGIO, \\\n", " api_key = CONST_GEOCODE_API_KEY) # összeállítottuk a Google Maps Geocoding API lekérdezés webcímét\n", " koordinatak = geocode_query(lnk) # megtörténik a tényleges lekérdezés\n", " if koordinatak.get(\"status_ok\") == 1:\n", " for j in zip(geo_oszlopok, [\"lat\", \"lng\"]):\n", " p.iloc[i, j[0]] = koordinatak.get(j[1]) # előbb a földrajzi szélesség, majd a földrajzi hosszúság\n", " if i < len(p) - 1:\n", " # Ajánlatos lehet pár másodperc szünetet tartani lekérdezések között, hogy a Google ne tekintse\n", " # visszaélésszerű felhasználásnak. Az utolsó elem után persze már ne várakozzunk :)\n", " time.sleep(CONST_SLEEP_GEOCODE_KOZOTT)\n", " else:\n", " for j in geo_oszlopok:\n", " p.iloc[i, j] = None # explicit törlés, hogy már létező DataFrame-re újrafuttatva nehogy téves érték maradjon benne\n", " i += 1\n", " return p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A függvények definíciója után jöhet a tulajdonképpeni futtatás!" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MegyeIrányítószámVárosKözterületgeo_szelesseggeo_hosszusag
0Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387
1Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422
2Budapest1052BudapestVárosház u. 9-11.47.49526819.054405
3Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978
\n", "
" ], "text/plain": [ " Megye Irányítószám Város Közterület geo_szelesseg \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "1 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "2 Budapest 1052 Budapest Városház u. 9-11. 47.495268 \n", "3 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. 46.907950 \n", "\n", " geo_hosszusag \n", "0 20.148387 \n", "1 21.625422 \n", "2 19.054405 \n", "3 19.691978 " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = geocode_dataframe(df, cim_oszlopok=(1, 2, 3), geo_oszlopok=(4, 5)) # a Megye oszloppal nem kezdek semmit, de a többi oszlop pozíciója fontos paraméter\n", "df.head() # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Amennyiben **hiányos (üres) koordinátát találunk**, tegyünk egy próbát, írjuk be az adott címet a Google Maps webböngészős felületére! Talán nem az API lekérdezéssel van ugyanis gond, hanem a Google Maps egyáltalán nem találja az adott címet!\n", "- az „u.” és az „utca” átváltása remekül megy a Google-nek\n", "- például az már megzavarhatja, és nemlétező címnek tekintheti, ha a Széchenyi István u. a címek forrásául szolgáló Excelben „Széchenyi I. u.”-ként szerepel, a Nagy Lajos király útja csonkolva, „Nagy L. kir.” formában, vagy éppen a 96-98-as házszám összecsúszva „9698”-ként van benne\n", "\n", "Az eredményt Excel-fájlba mentem." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# írjuk ki az eredményt egy másik Excel-fájlba\n", "writer = pd.ExcelWriter(\"Városháza (földrajzi koordinátákkal).xlsx\", engine=\"xlsxwriter\")\n", "df.to_excel(writer, sheet_name=\"Munka1\", index=False)\n", "writer.save()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Az első feladattal tehát készen volnánk: előálltak a városházák geokoordinátái." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2) Légvonalban mért távolság\n", "\n", "Második feladatként számoljuk ki a koordináták összes többi koordinátától való, légvonalban mért távolságát!\n", "\n", "Mint azt földrajzórán megtanultuk, Földünk „Föld-alakú”, azaz „geoid” formájú, nem pedig tökéletes gömb. Mégis annak szokás tekinteni, és a légvonalban mért távolságot egy gömbfelszín két pontja közötti, a felszínen mért legrövidebb távolságként értelmezni.\n", "\n", "Letöltök egy kis Python modult (`pip install haversine`), és felhasználom. Két, Python tuple formájában beadott földrajzi koordináta távolságát adja vissza kilométerben (igény esetén mérföldben)." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 1243.399 kilométer\n", " 772.612 mérföld\n" ] } ], "source": [ "# illusztráció: földrajzi koordináták távolsága légvonalban, tökéletes gömbnek tekintett Föld felszínén mérve\n", "# haversine Python-modul, és https://en.wikipedia.org/wiki/Haversine_formula\n", "koordinatak_budapest = (47.5, 19.03) # Python tuple, szélesség és hosszúság\n", "koordinatak_parizs = (48.8530511, 2.3496311) # Python tuple, szélesség és hosszúság\n", "for i, mertekegyseg in enumerate([\"kilométer\", \"mérföld\"]):\n", " tav = haversine.haversine(koordinatak_budapest, koordinatak_parizs, miles=bool(i==1)) # alapból kilométer, s miles=True esetén mérfőld\n", " s = \"{:{szeles}.{tizedes}f} {egyseg}\".format(tav, szeles=10, tizedes=3, egyseg=mertekegyseg)\n", " print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A koordinátás DataFrame-ből (táblázatból) párosításokat készítek: „egyirányú” módon, tehát pl. egy Budapest-Debrecen távot nem érdemes kétszer kiszámoltatni, oda-vissza. Egy pontnak az önmagától vett távolságára sem vagyunk kíváncsiak, értelemszerűen." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Megye_1Irányítószám_1Város_1Közterület_1geo_szelesseg_1geo_hosszusag_1Megye_2Irányítószám_2Város_2Közterület_2geo_szelesseg_2geo_hosszusag_2
0Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422
1Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Budapest1052BudapestVárosház u. 9-11.47.49526819.054405
2Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978
3Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Budapest1052BudapestVárosház u. 9-11.47.49526819.054405
4Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978
5Budapest1052BudapestVárosház u. 9-11.47.49526819.054405Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978
\n", "
" ], "text/plain": [ " Megye_1 Irányítószám_1 Város_1 Közterület_1 geo_szelesseg_1 \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "1 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "2 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "3 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "4 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "5 Budapest 1052 Budapest Városház u. 9-11. 47.495268 \n", "\n", " geo_hosszusag_1 Megye_2 Irányítószám_2 Város_2 Közterület_2 \\\n", "0 20.148387 Hajdú-Bihar 4024 Debrecen Piac u. 20. \n", "1 20.148387 Budapest 1052 Budapest Városház u. 9-11. \n", "2 20.148387 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "3 21.625422 Budapest 1052 Budapest Városház u. 9-11. \n", "4 21.625422 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "5 19.054405 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "\n", " geo_szelesseg_2 geo_hosszusag_2 \n", "0 47.529631 21.625422 \n", "1 47.495268 19.054405 \n", "2 46.907950 19.691978 \n", "3 47.495268 19.054405 \n", "4 46.907950 19.691978 \n", "5 46.907950 19.691978 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Minden koordinátának minden másikkal vett párosítása, de csak egyszer (nem \"oda-vissza\")\n", "df2 = pd.merge(df.reset_index().assign(descartes_segedvaltozo=1),\n", " df.reset_index().assign(descartes_segedvaltozo=1),\n", " on=\"descartes_segedvaltozo\",\n", " suffixes=(\"_1\", \"_2\")) \\\n", " .drop(\"descartes_segedvaltozo\", axis=1) \\\n", " .query(\"index_1 < index_2\") \\\n", " .sort_values([\"index_1\", \"index_2\"]) \\\n", " .reset_index(drop=True) \\\n", " .drop([\"index_1\", \"index_2\"], axis=1)\n", "df2.head(10) # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alkalmazzuk a föntebb bemutatott modulban található függvényt, s az így előálló távolságokat új oszlopként adjuk hozzá a DataFrame-hez." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Megye_1Irányítószám_1Város_1Közterület_1geo_szelesseg_1geo_hosszusag_1Megye_2Irányítószám_2Város_2Közterület_2geo_szelesseg_2geo_hosszusag_2tavolsag_legvonalban
0Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422180.820625
1Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Budapest1052BudapestVárosház u. 9-11.47.49526819.054405161.078935
2Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197880.592251
3Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Budapest1052BudapestVárosház u. 9-11.47.49526819.054405193.123654
4Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978161.550872
5Budapest1052BudapestVárosház u. 9-11.47.49526819.054405Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197881.147876
\n", "
" ], "text/plain": [ " Megye_1 Irányítószám_1 Város_1 Közterület_1 geo_szelesseg_1 \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "1 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "2 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "3 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "4 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "5 Budapest 1052 Budapest Városház u. 9-11. 47.495268 \n", "\n", " geo_hosszusag_1 Megye_2 Irányítószám_2 Város_2 Közterület_2 \\\n", "0 20.148387 Hajdú-Bihar 4024 Debrecen Piac u. 20. \n", "1 20.148387 Budapest 1052 Budapest Városház u. 9-11. \n", "2 20.148387 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "3 21.625422 Budapest 1052 Budapest Városház u. 9-11. \n", "4 21.625422 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "5 19.054405 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "\n", " geo_szelesseg_2 geo_hosszusag_2 tavolsag_legvonalban \n", "0 47.529631 21.625422 180.820625 \n", "1 47.495268 19.054405 161.078935 \n", "2 46.907950 19.691978 80.592251 \n", "3 47.495268 19.054405 193.123654 \n", "4 46.907950 19.691978 161.550872 \n", "5 46.907950 19.691978 81.147876 " ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tav = df2.apply(lambda x: haversine.haversine((x[\"geo_szelesseg_1\"], x[\"geo_hosszusag_1\"]), (x[\"geo_szelesseg_2\"], x[\"geo_hosszusag_2\"])), axis=1)\n", "df2[\"tavolsag_legvonalban\"] = tav\n", "df2.head(10) # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Íme, a második feladat is elkészült: megtudtuk a koordináták légvonalban mért távolságát. A Python Pandas DataFrame jobb oldali szélső oszlopában immár ez látható." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3) Közúton mért távolság\n", "\n", "Harmadik feladatként számoljuk ki a koordináták összes többi koordinátától való, közúton mért távolságát!\n", "\n", "Ezt a _**Google Maps Distance Matrix API**_-val tudjuk lekérdezni. A Google felé földrajzi koordinátákat kell küldenünk, és **igazán változatos beállítási lehetőségeink vannak**:\n", "- autó helyett esetleg bicajjal kívánjuk megtenni a távot (utóbbi esetben városon belül a kijelölt bicikliutakon igyekszik tervezni a Google)\n", "- vagy távol kívánunk maradni a kompoktól (ahol benzint tudunk ugyan spórolni, de a várakozás miatt mégis tovább tarthat az út)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def distancematrix_query(webcim, varakozas=CONST_SLEEP_ERROR_KEZDETI, max_varakozas=CONST_SLEEP_ERROR_MAXIMUM):\n", " \"\"\"A Google Maps Distance Matrix API felé indított lekérdezések végrehajtása. Az eredmény Python dictionary (kulcs-érték szótár) típusú.\"\"\"\n", " tav = None\n", " status_ok = 0\n", " rj = requests.get(webcim).json()\n", " if rj.get(\"status\") == \"OK\":\n", " try:\n", " # Itt persze lenne tér némi barkácsolásra, például hogy ne fixen a Google által fölkínált\n", " # legelső lehetőséget használjuk (Pythonban: 0 indexű találat, rj[\"rows\"][0]),\n", " # hanem egy másikat, esetleg többet is. Az egyszerűség kedvéért most csak a legelső szerepel.\n", " # Tudtommal a Google API válaszában a \"distance\" amúgy mindig méterben áll rendelkezésre,\n", " # és a mérföld/kilométer beállítás csak a \"text\" elemet befolyásolja.\n", " tav = int(rj[\"rows\"][0][\"elements\"][0][\"distance\"][\"value\"]) / 10**3 # kilométer-átváltás\n", " status_ok = 1\n", " except:\n", " pass\n", " return {\"status_ok\": status_ok,\n", " \"tav\": tav}\n", " elif rj.get(\"status\") == \"UNKNOWN_ERROR\" or rj.get(\"status\") is None:\n", " if varakozas > max_varakozas:\n", " return {\"status_ok\": status_ok,\n", " \"tav\": tav}\n", " else:\n", " time.sleep(varakozas)\n", " return distancematrix_query(webcim, varakozas*2)\n", " else:\n", " return {\"status_ok\": status_ok,\n", " \"tav\": tav} # \"INVALID_REQUEST\", \"MAX_ELEMENTS_EXCEEDED\", \"OVER_QUERY_LIMIT\", \"REQUEST_DENIED\" esetén nem futunk neki ismét" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ha a kezdő- vagy végpont koordinátája nem elérhető, akkor be sem küldöm az API-nak útvonaltervezésre, így gyorsítva a futást. **A koordináták oszlopait paraméterként adom meg**, és ezt mindig földrajzi szélesség, majd földrajzi hosszúság sorrendben teszem." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def distancematrix_dataframe(p, geo_oszlopok=((0, 1), (2, 3)), tav_oszlop=4):\n", " \"\"\"A Google Maps Distance Matrix API felé indított lekérdezés összeállítása, és az eredmények tárolása.\"\"\"\n", " i = 0\n", " while i < len(p):\n", " if any([np.isnan(p.iloc[i, geo_oszlopok[j][k]]) for j in range(2) for k in range(2)]): # hiányzó koordináta van, ezért nem számolunk távolságot\n", " p.iloc[i, tav_oszlop] = None # explicit törlés, hogy már létező DataFrame-re újrafuttatva nehogy téves érték maradjon benne\n", " else: # nincs hiányzó koordináta, tehát számolunk távolságot\n", " # legyártjuk a Google Maps Distance Matrix API által várt, vesszővel elválasztott, tizedes ponttal működő koordinátás input string-eket, pl. \"46.254568,20.148387\"\n", " geo1 = \"{},{}\".format(*(p.iloc[i, geo_oszlopok[0][j]] for j in range(2)))\n", " geo2 = \"{},{}\".format(*(p.iloc[i, geo_oszlopok[1][j]] for j in range(2)))\n", " s = \"https://maps.googleapis.com/maps/api/distancematrix/json?origins={}&destinations={}&mode=driving&units=metric&avoid=ferries&key={api_key}\".format(geo1, geo2, api_key=CONST_DISTANCE_API_KEY) # a lekérdezés webcíme; autózás (driving) helyett akár gyaloglás (walking) vagy biciklizés (bicycling) is megadható! Utóbbi esetben városon belül előnyben részesíti a kiépített bicikliutakat. \n", " valasz = distancematrix_query(s) # lekérjük a távolságot az API-tól\n", " if valasz.get(\"status_ok\") == 1:\n", " p.iloc[i, tav_oszlop] = valasz.get(\"tav\")\n", " if i < len(p) - 1:\n", " # Ajánlatos lehet pár másodperc szünetet tartani lekérdezések között, hogy a Google ne tekintse\n", " # visszaélésszerű felhasználásnak. Az utolsó elem után persze már ne várakozzunk :)\n", " time.sleep(CONST_SLEEP_DISTANCEMATRIX_KOZOTT)\n", " i += 1\n", " return p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Új oszlopot hozok létre, oda írom majd a lekérdezés eredményét." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 6 entries, 0 to 5\n", "Data columns (total 14 columns):\n", "Megye_1 6 non-null object\n", "Irányítószám_1 6 non-null int64\n", "Város_1 6 non-null object\n", "Közterület_1 6 non-null object\n", "geo_szelesseg_1 6 non-null float64\n", "geo_hosszusag_1 6 non-null float64\n", "Megye_2 6 non-null object\n", "Irányítószám_2 6 non-null int64\n", "Város_2 6 non-null object\n", "Közterület_2 6 non-null object\n", "geo_szelesseg_2 6 non-null float64\n", "geo_hosszusag_2 6 non-null float64\n", "tavolsag_legvonalban 6 non-null float64\n", "tavolsag_kozuton 0 non-null float64\n", "dtypes: float64(6), int64(2), object(6)\n", "memory usage: 752.0+ bytes\n" ] } ], "source": [ "df2[\"tavolsag_kozuton\"] = None\n", "df2[\"tavolsag_kozuton\"] = df2[\"tavolsag_kozuton\"].astype(float) # tizedes tört adattípus\n", "df2.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Az adott Python Pandas DataFrame újabb oszloppal bővült, s a legutolsó (jobb szélső) oszlopban lesz látható a friss eredményünk.\n", "\n", "Jöhet a tulajdonképpeni futtatás!" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Megye_1Irányítószám_1Város_1Közterület_1geo_szelesseg_1geo_hosszusag_1Megye_2Irányítószám_2Város_2Közterület_2geo_szelesseg_2geo_hosszusag_2tavolsag_legvonalbantavolsag_kozuton
0Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422180.820625216.902
1Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Budapest1052BudapestVárosház u. 9-11.47.49526819.054405161.078935171.474
2Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197880.59225190.825
3Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Budapest1052BudapestVárosház u. 9-11.47.49526819.054405193.123654231.040
4Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978161.550872182.643
5Budapest1052BudapestVárosház u. 9-11.47.49526819.054405Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197881.14787684.071
\n", "
" ], "text/plain": [ " Megye_1 Irányítószám_1 Város_1 Közterület_1 geo_szelesseg_1 \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "1 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "2 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "3 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "4 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "5 Budapest 1052 Budapest Városház u. 9-11. 47.495268 \n", "\n", " geo_hosszusag_1 Megye_2 Irányítószám_2 Város_2 Közterület_2 \\\n", "0 20.148387 Hajdú-Bihar 4024 Debrecen Piac u. 20. \n", "1 20.148387 Budapest 1052 Budapest Városház u. 9-11. \n", "2 20.148387 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "3 21.625422 Budapest 1052 Budapest Városház u. 9-11. \n", "4 21.625422 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "5 19.054405 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "\n", " geo_szelesseg_2 geo_hosszusag_2 tavolsag_legvonalban tavolsag_kozuton \n", "0 47.529631 21.625422 180.820625 216.902 \n", "1 47.495268 19.054405 161.078935 171.474 \n", "2 46.907950 19.691978 80.592251 90.825 \n", "3 47.495268 19.054405 193.123654 231.040 \n", "4 46.907950 19.691978 161.550872 182.643 \n", "5 46.907950 19.691978 81.147876 84.071 " ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = distancematrix_dataframe(df2, geo_oszlopok=((4, 5), (10, 11)), tav_oszlop=13) # paraméterként az oszlop-indexek\n", "df2.head(10) # áttekintés; csak az első néhány értéket jelenítjük meg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Készen vagyunk, a harmadik feladat eredménye a közúton mért távolság." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Megye_1Irányítószám_1Város_1Közterület_1geo_szelesseg_1geo_hosszusag_1Megye_2Irányítószám_2Város_2Közterület_2geo_szelesseg_2geo_hosszusag_2tavolsag_legvonalbantavolsag_kozutonkozut_legvonal_arany
0Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422180.820625216.9021.199542
1Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Budapest1052BudapestVárosház u. 9-11.47.49526819.054405161.078935171.4741.064534
2Csongrád6720SzegedSzéchenyi tér 10.46.25456820.148387Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197880.59225190.8251.126969
3Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Budapest1052BudapestVárosház u. 9-11.47.49526819.054405193.123654231.0401.196332
4Hajdú-Bihar4024DebrecenPiac u. 20.47.52963121.625422Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.691978161.550872182.6431.130560
5Budapest1052BudapestVárosház u. 9-11.47.49526819.054405Bács-Kiskun6000KecskemétKossuth tér 1.46.90795019.69197881.14787684.0711.036022
\n", "
" ], "text/plain": [ " Megye_1 Irányítószám_1 Város_1 Közterület_1 geo_szelesseg_1 \\\n", "0 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "1 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "2 Csongrád 6720 Szeged Széchenyi tér 10. 46.254568 \n", "3 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "4 Hajdú-Bihar 4024 Debrecen Piac u. 20. 47.529631 \n", "5 Budapest 1052 Budapest Városház u. 9-11. 47.495268 \n", "\n", " geo_hosszusag_1 Megye_2 Irányítószám_2 Város_2 Közterület_2 \\\n", "0 20.148387 Hajdú-Bihar 4024 Debrecen Piac u. 20. \n", "1 20.148387 Budapest 1052 Budapest Városház u. 9-11. \n", "2 20.148387 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "3 21.625422 Budapest 1052 Budapest Városház u. 9-11. \n", "4 21.625422 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "5 19.054405 Bács-Kiskun 6000 Kecskemét Kossuth tér 1. \n", "\n", " geo_szelesseg_2 geo_hosszusag_2 tavolsag_legvonalban tavolsag_kozuton \\\n", "0 47.529631 21.625422 180.820625 216.902 \n", "1 47.495268 19.054405 161.078935 171.474 \n", "2 46.907950 19.691978 80.592251 90.825 \n", "3 47.495268 19.054405 193.123654 231.040 \n", "4 46.907950 19.691978 161.550872 182.643 \n", "5 46.907950 19.691978 81.147876 84.071 \n", "\n", " kozut_legvonal_arany \n", "0 1.199542 \n", "1 1.064534 \n", "2 1.126969 \n", "3 1.196332 \n", "4 1.130560 \n", "5 1.036022 " ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2[\"kozut_legvonal_arany\"] = df2[\"tavolsag_kozuton\"] / df2[\"tavolsag_legvonalban\"] # csak kiváncsiságból\n", "df2.head(10)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# írjuk ki az eredményt egy Excel-fájlba\n", "writer = pd.ExcelWriter(\"Városháza (távolságok).xlsx\", engine=\"xlsxwriter\")\n", "df2.to_excel(writer, sheet_name=\"Munka1\", index=False)\n", "writer.save()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ennyi hát, ízelítőül." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###
Köszönöm a figyelmet, s jó munkát kívánok mindenkinek!
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1" } }, "nbformat": 4, "nbformat_minor": 2 }