Tartalom: Fájlok, flagek (r, w, b, +), szöveges formátumok, csv, matplotlib
A mai előadás során a matplotlib
néhány funkcióját vesszük sorra. A matplotlib
egy python modul, ami egyszerűbb (és összettettebb) grafikonok megjelenítését segítő függvények, osztályok definícióit tartalmazza. Ennek telepítése után a
import matplotlib.pyplot as plt
parancsával importálhatjuk. Ha (mint jelen esetben is) jupyter notebookban, és nem felugró ablakként szeretnénk a grafikonokat megjeleníteni akkor szükség lesz a
%matplotlib inline
parancsra is.
Megjegyzés: Bár a matplotlib
az egyik legelterjedtebb grafikonokkal foglakozó csomag, sokkal gyorabb működést tud a PyQtGraph
.
Nézzünk pár egyszerű példát matplotlib
-re.
import matplotlib.pyplot as plt
%matplotlib inline
x0 = [1, 2, 3, 4, 5, 6, 7]
y0 = [9, 8, 2, 6, 5, 4, 3]
y1 = [3, 4, 0, 9, 9, 1, 0]
plt.plot(x0, y1)
plt.show()
plt.plot(x0, y1, "o--")
plt.show()
A "o--"
a markert és az összeköttetés vonalstílusát jelzi.
A leggyakoribb markerek:
"."
pont,
"o"
kör,
"v"
lefelé háromszög,
"^"
felfelé háromszög,
"<"
balra háromszög,
">"
jobbra háromszög,
"x"
x jel,
"+"
plusz jel,
"s"
négyzet alakzat
"D"
gyémánt alak.
A vonal stílusa lehet pl. '-'
folytonos, '--'
szaggatott, '-.'
pont-vonal vagy ':'
pontozott.
A leggyakoribb színek:
'b'
kék,
'g'
zöld,
'r'
piros,
'y'
sárga,
'k'
fekete
'w'
fehér.
Számos grafikon típus létezik matplotlib
-ben, mi a plot
-ot, a bar
-t, a barh
-t és a scatter
-t vizsgáljuk részletesebben.
Az alpha=0.6
paraméter 60%-os átlátszóságot jelent.
A plt.grid(True)
segítségével a rácsot jeleníthetjük meg.
A függvényeket megjeleníthetjük egy tengelyen is pl.:
plt.plot(x0, y1, "rx-", label="Y1 értékei")
plt.bar(x0, y0, alpha=0.6, label="Y0 értékei")
plt.xlabel("x tengely")
plt.ylabel("y tengely")
plt.grid(True)
plt.legend()
plt.show()
Létrehozhatunk ábrákat a plt.figure(1)
, plt.figure(2)
, stb. segítségével. Ezekben akár alábrákat is készíthetünk subplot
-tal. Például a következő esetben egy 2 soros 1 oszlopos subplot
2. elemére hivatkozunk:
plt.subplot(212)
Például 2x2 oszlop / sor esetén maximum a 4. elemre hivatkozhatunk.
plt.subplot(224)
Nézzük ezeket példán keresztül:
import matplotlib.pyplot as plt
%matplotlib inline
x0 = [1, 2, 3, 4, 5, 6, 7]
y0 = [9, 8, 2, 6, 5, 4, 3]
y1 = [3, 4, 0, 9, 9, 1, 0]
plt.figure(1, figsize=(8,6))
plt.subplot(211)
plt.title("211-es subplot")
plt.plot(x0, y0, 'bo-', x0, y1, 'kx:')
plt.subplot(212)
plt.title("212-es subplot")
plt.plot(x0, y1, 'r--')
plt.show()
plt.figure(2, figsize=(10,4))
plt.subplot(121)
plt.title("121-es subplot")
plt.plot(x0, y0, 'bo-', x0, y1, 'kx:')
plt.subplot(122)
plt.title("122-es subplot")
plt.plot(x0, y1, 'r--')
plt.show()
Windowsban visszaperrel (backslash) jelöljük az elérési út összefűzését, míg Linuxon perrel (slash).
Linux verzió:
/herno/Desktop/textfile.txt
Windows verzió:
\\herno\\Desktop\\textfile.txt
Hogy ezt az ellenmondást feloldjuk, a Pythonban használhatjuk az os.path.join
függvényt. Például, próbáljuk ki a következő kódot:
import os
print(os.path.join("herno", "Desktop", "textfile.txt"))
ekkor az eredmény Linuxon
/herno/Desktop/textfile.txt
lesz, míg Windowson
herno\Desktop\textfile.txt
vagy
"\\herno\\Desktop\\textfile.txt"
Példa feladatunk telemetriás adatokból indul ki.
A csatolt .csv
fájlok táblázatos formában tartalmazzák egyetemünk Szenergy hallgatói csapatának telemetriás adatait többek közt spanyol (Murcia), holland (Rotterdam) és angol (London) versenyekről. A csapat belső szabályzatának értelmében ezek érzékeny adatok, így nincs benne minden mért adat, illetve kisebb mintavételezéssel vannak bent adatok. Ettől függetlenül a .csv
-k valós versenyeken mért sebességeket és egy egyéb adatokat tartalmaznak. A mért adatok nem ekvidisztánsak, nem tökéletesen tartják a 2 Hz-es (0,5 másodperc) mintavételezést, ennek oka, hogy egy mobil internettel a verseny közben feltöltött adatbázisból származnak.
A .csv
fájlok nagyjából így néznek ki:
Time;SpeedRpm;SpeedKmph;GasSignal;LapNumber;MotorCommError; ... AuxiliaryBattery
38,45;0;0;0,019043;0;false;false;false;14;0,80563;51,5603;false;1;12,9713
41,75;0;0;0,0193481;0;false;false;false;14;0,80563;51,5603;false;1;12,9713
42,3;0;0;0,0190735;0;false;false;false;14;0,80563;51,5603;false;1;12,9687
...
Time | SpeedRpm | SpeedKmph | GasSignal | LapNumber | MotorCommError | ... | AuxiliaryBattery | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
38,45 | 0 | 0 | 0,019043 | 0 | false | ... | 12,9713 | |||||||
41,75 | 0 | 0 | 0,0193481 | 0 | false | ... | 12,9713 | |||||||
42,3 | 0 | 0 | 0,0190735 | 0 | false | ... | 12,9687 |
Fontosabb mezők:
(float)
(float)
(int)
(float)
Írjuk ki 1010 és 1015 másodperc között a idő értékekhez tartozó akkumulátorfeszültséget és sebességet.
Használjuk ehhez a with
utasítást:
with open(file, 'rt') as csvfile: # innentől a csvfile- segítségével hivatkozhatunk a fájlra
import csv
import os
import matplotlib.pyplot as plt
%matplotlib inline
file = os.path.join("data", "szenergy_2014_10_17_16_06_rotterdam.csv")
with open(file, 'rt') as csvfile:
spamreader = csv.DictReader(csvfile, delimiter=';', quotechar='"')
for row in spamreader:
if 1010 < float(row['Time'].replace(',','.')) < 1015:
print("%s s\t%s km/h\t%s v" % (row['Time'], row['SpeedKmph'], row['BmsVoltage']))
1010,4 s 22,0439 km/h 50,199 v 1011,15 s 21,352 km/h 50,199 v 1011,65 s 20,9869 km/h 50,199 v 1012,25 s 20,942 km/h 50,199 v 1012,85 s 20,7178 km/h 50,199 v 1013,4 s 20,2373 km/h 50,199 v 1013,95 s 19,9042 km/h 50,199 v 1014,45 s 19,8145 km/h 50,199 v
Rajzoltassuk ki a 2-4. kör sebességeit km/h-ban.
file = os.path.join("data", "szenergy_2017_05_25_17_35_london.csv")
#file = os.path.join("data", "szenergy_2014_10_17_16_06_rotterdam.csv")
with open(file, 'rt') as csvfile:
spamreader = csv.DictReader(csvfile, delimiter=';', quotechar='"')
xt = []
ys = []
for row in spamreader:
if 2 <= int(row['LapNumber'].replace(',','.')) <= 4:
xt.append(float(row['Time'].replace(',','.')))
ys.append(float(row['SpeedKmph'].replace(',','.')))
plt.plot(xt, ys, label = file)
plt.xlabel("Idő (s)")
plt.ylabel("Sebesség (km/h)")
plt.legend()
plt.show()
Ahogy látszik a jármű 20 és 30 km/h közötti sebességgel haladt legtöbbször, lévén a verseny célja az üzemanyag takarékosság, ahol nem a leggyorsabb, hanem a legkevesebb felhasznált energiával megtett kör a feladat.
Az említett barh
egy horizontális sávos diagram. Nézzük meg ennek használatát a nobel_price.csv
segítségével, ami a következőképp épül fel:
Country | Nobel price (2017) | Population |
---|---|---|
Algeria | 2 | 41 318 142 |
Argentina | 5 | 44 271 041 |
Australia | 12 | 24 450 561 |
.... | ... | ... |
Hungary | 13 | 9 721 559 |
.... | ... | ... |
Venezuela | 1 | 31 977 065 |
Vietnam | 1 | 93 447 601 |
Yemen | 1 | 28 250 420 |
import csv
import os
import matplotlib.pyplot as plt
nobel_file = os.path.join("data", "nobel_price.csv")
with open(nobel_file, 'rt') as nfile:
spamreader = csv.DictReader(nfile, delimiter=";")
# Country;Nobel price (2017);Population
for row in spamreader:
if int(row['Nobel price (2017)']) > 10:
plt.barh(row['Country'], int(row['Population']), 0.4)
plt.xticks(rotation=90)
plt.title("10 Nobel díj feletti országok népessége")
plt.show()
import csv
import os
import matplotlib.pyplot as plt
nobel_file = os.path.join("data", "nobel_price.csv")
plt.figure(figsize=(6,14))
nobel, country = [], []
with open(nobel_file, 'rt') as nfile:
spamreader = csv.DictReader(nfile, delimiter=";")
# Country;Nobel price (2017);Population
for row in spamreader:
nobel.append(int(row['Nobel price (2017)']) / int(row['Population']) * 10000000)
country.append(row['Country'])
d = dict(zip(country, nobel))
for w in sorted(d, key=d.get, reverse=False):
if w == "Hungary":
plt.barh(w, d[w], color = 'r', alpha=0.6)
else:
plt.barh(w, d[w], color = 'b', alpha=0.6)
plt.title("Nobel díj / 10 millió fő")
plt.show()
További lehetőségünk van a scatter
használatával. Ez pontdiagramot hoz létre, különböző méretű körökkel. Vegyük példának az európai országok adatait - tabokkal elválasztva - tartalmazó europe_countries.tsv
.
A scatter
általános alakja:
plt.scatter(x, y, s = méret)
Feliratot a annotate
készít:
plt.annotate("Felirat szövege", (x, y))
import csv
import os
import matplotlib.pyplot as plt
nobel_file = os.path.join("data", "europe_countries.tsv")
plt.figure(figsize=(10,6))
with open(nobel_file, 'rt') as nfile:
spamreader = csv.DictReader(nfile, delimiter="\t")
for row in spamreader:
plt.scatter(float(row["longitude"]), float(row["latitude"]), s = int(float(row["area"]))/100, alpha=0.2)
plt.annotate(row["ISOa3"], (float(row["longitude"]), float(row["latitude"])) )
plt.show()