11. gyakorlat¶
A gyakorlat anyaga¶
Numpy¶
A Numpy a Numerical Python rövidítése, és az egyik legelterjedtebb modul, ha tudományos számításokról van szó.
Az alap Python listák helyett egy sokkal jobban optimalizált tömb objektumot biztosít (ndarray néven).
Különbségek az ndarray
és a sima python list
között:
- A listákkal ellentétben a NumPy tömböknek fix mérete van, ha megváltoztatjuk egy ndarray méretét a létrejötte után, akkor az eredeti törlődik és egy új tömb jön létre.
- Egy ndarray-ben csak ugyan olyan adattípusú elemek lehetnek.
NumPy tömbök létrehozása¶
- Python listából
- Numpy függvényekkel
import numpy as np
#teli 0 mátrix
arr1 = np.zeros((2,3)) # [[0,0,0],
# [0,0,0]]
# paramétere egy int vagy tuple, ami a méretét adja meg
#teli 1 mátrix
arr2 = np.ones((1,2)) # [[1,1]]
# paramétere egy int vagy tuple, ami a méretét adja meg
#teli n mátrix
arr3 = np.full((2,2), 5) # [[5,5],
# [5,5]]
# paraméterei egy int vagy tuple, ami a méretét adja meg és egy valós szám, ami a tömb elemeit
#python range-hez hasonlóan
arr3 = np.arange(10) # [0,1,2,3,4,5,6,7,8,9]
arr4 = np.arange(2,5,2) # [2,4]
# paraméterei az intervallum eleje (opcionális), vége és a lépésköz
#adott invervallumon n db szám létrehozása egyenletes közzel
arr5 = np.linspace(0,4,6) # [0,0.8,1.6,2.4,3.2,4]
# paraméterei az intervallum eleje, vége és hogy hány számot szeretnénk
ndarray adattagok¶
- ndim - a tömb dimenzióinak száma
- shape - a tömb konkrét dimenziói, ez egy ndim hosszú tuple
- size - a tömb elemeinek száma
- dtype - a tömb elemeinek adattípusa
- itemsize - a tömb egy elemének mérete byte-ban
Indexelés¶
import numpy as np
matrix = [[1,2,3],[4,5,6]]
#indexelés pythonban
masodiksor_elso = matrix[1][0] # 4
#numpy indexelés
matrix = np.array(matrix) # hogy lista helyett ndarray legyen
masodiksor_elso = matrix[1,0] # 4
# a sima matrix[1][0] is ugyan úgy működik
#index tömbbel
array = np.arange(10,1,-1) # [10,9,8,7,6,5,4,3,2]
index = np.array([3,4,2,3]) #
x = array[index] # [7,6,8,7]
Műveletek¶
Sima python listák elemeinek összeadása a legalapabb módszerrel¶
NumPy változat¶
Ugyan így az összes többi alapműveletre isTovábbi NumPy műveletek¶
import numpy as np
x = np.array([1,2,3])
sum = np.sum(x) # lista vagy mátrix elemeinek összege
matrix1 = np.array([[1,2],[3,4]])
matrix2 = np.array([[5,6],[7,8]])
matrixszorzat = np.dot(matrix1,matrix2) # mátrixszorzás (nem elemenként)
Reshape¶
A tömb méretének befolyásolására szolgál, hozzáadhatunk vagy elvehetünk dimenziókat vele, ameddig a dimenziók szorzata egyenlő az elemek számával.
import numpy as np
arr = np.arange(12) # [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
matrix = arr.reshape(4,3) # [[ 0, 1, 2],
# [ 3, 4, 5],
# [ 6, 7, 8],
# [ 9, 10, 11]]
#vissza vektorrá
arr2 = matrix.reshape(-1) # [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Stack¶
Mátrixok egymás mellé és egymásra illesztése
import numpy as np
arr1 = np.array([[1,2],[3,4]])
arr2 = np.array([[5,6],[7,8]])
arr3 = np.hstack((arr1,arr2)) # [[1, 2, 5, 6],
# [3, 4, 7, 8]]
arr4 = np.vstack((arr1,arr2)) # [[1, 2],
# [3, 4],
# [5, 6],
# [7, 8]]
Alternatívák¶
Tensorflow és PyTorch¶
Mindkét modult főleg gépi tanulásnál használják, bár a szimplább, itt bemutatott dolgokra is képesek. Ugyan úgy megtalálható bennük egy n dimenziós mátrix reprezentására használható adattípus, csak ndarray helyett tensor néven. A főbb különbség a performancián jön csak ki, ugyan is míg a NumPy csak CPU-n tud számolni, addig az említett két modulban szerepel GPU támogatás is, ami bizonyos esetekben gyorsabb. A kisebb mátrixműveletek elvégézésénél még a NumPy nyer sebességben, még GPU-n se verik meg, viszont ez főleg annak tudható be, hogy a CPU sokkal gyorsabban eléri az adatot, mint a GPU. Ahogy egyre jobban elenyészővé válik az adat elérésének ideje (a tényleges számítás idejének növekedésével), úgy ezek a modulok a GPU-n számolva jobban teljesítenek.
Pandas¶
Adatelemzéshez elengedhetetlen python modul, főleg táblázatokból és adatbázisokból kinyert adatok feldolgozására használják, amihez egy a python-os dictionary-hez hasonló, de jobban optimalizált adatszerkezetet biztosít.
Series¶
A modul saját objektuma, ami egy táblázat egy oszlopára hasonlít, egydimenziós tömbként reprezentál bármilyen típusú adatot.
import pandas as pd
array = [1,3,5]
series = pd.Series(array)
print(series) # 0 1
# 1 3
# 2 5
# dtype: int64
Minden sor címkézve is van, ugyan úgy mint egy dictionary-ben. Alapértelmezetten ez a címke a sorszámot jelöli.
import pandas as pd
array = [1,3,5]
series = pd.Series(array,index = ["elso","masodik","harmadik"])
print(series) # elso 1
# masodik 3
# harmadik 5
# dtype: int64
Python dictionary átalakítása:
import pandas as pd
dictionary = {"elso": 1, "masodik" : 3, "harmadik": 5}
series = pd.Series(dictionary)
print(series) # elso 1
# masodik 3
# harmadik 5
# dtype: int64
DataFrame¶
A modul saját objektuma, ami egy 2D mátrixra vagy egy teljes táblázatra hasonlít.
import pandas as pd
data = {
"nem" : ["ferfi","no","no","ferfi"],
"kor" : [23,32,42,19]
}
df = pd.DataFrame(data)
print(df) # Alapértelmezetten csak az első és utolsó 5 sort írja ki,
# ha az egész kell print(df.to_string())
# nem kor
# 0 ferfi 23
# 1 no 32
# 2 no 42
# 3 ferfi 19
print(df.loc[0]) # nem ferfi
# kor 23
# Name: 0, dtype: object
print(df.loc[[0,2]]) # nem kor
# 0 ferfi 23
# 2 no 42
Adatok beolvasása¶
A modul rengeteg fájlformátumból tud beolvasni (https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html), köztük csv, json, excel és sql támogatás is van. Ilyenkor egyből DataFrame objektumként kapjuk meg a tartalmat.
import pandas as pd
df1 = pd.read_csv("data.csv")
df2 = pd.read_json("data.json")
df3 = pd.read_excel("data.xls","Sheet1")
Az adat megjelenítése¶
import pandas as pd
data = {
"nem" : ["ferfi","no","no","ferfi"],
"kor" : [23,32,42,19]
}
df = pd.DataFrame(data)
print(df.head(2)) # Az első 2 sor megjelenítése
print(df.tail(2)) # Az utolsó 2 sor megjelenítése
print(df.info()) # Alap információk a DataFrame-ről
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 4 entries, 0 to 3 <-- sorok száma
# Data columns (total 2 columns): <-- oszlopok száma
# # Column Non-Null Count dtype <-- az oszlopok neve és adattípusa
# --- ------ -------------- -----
# 0 nem 4 non-null object
# 1 kor 4 non-null int64
# dtypes: int64(1), object(1)
# memory usage: 192.0+ bytes
# None
print(df.mean()) # A sorok átlaga oszloponként
print(df.count()) # A nem üres sorok száma oszloponként
print(df.max()) # A legnagyobb érték oszloponként (szövegnél ábécé sorrendben utolsó)
print(df.min()) # A legkisebb érték oszloponként (szövegnél ábécé sorrendben első)
print(df.median()) # A sorok mediánja oszloponként
DataFrame-ek összekötése¶
import pandas as pd
data1 = {
"nem" : ["ferfi","no","no","ferfi"],
"kor" : [23,32,42,19]
}
data2 = {
"nem" : ["ferfi","ferfi"],
"kor" : [30,65]
}
data3 = {
"hazas" : [True,False]
}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
df3 = pd.DataFrame(data3)
df1.append(df2) # További sorok beszúrása
df3 = pd.concat([df1,df3],axis=1) # df1 oszlopai mellé kerülnek df2 oszlopai
# nem kor hazas
# 0 ferfi 23 True
# 1 no 32 False
# 2 no 42 NaN
# 3 ferfi 19 NaN
Hiányos adatok pótlása/eltávolítása¶
print(pd.isnull(df3)) # egy True/False táblázatot ad vissza, ahol a True értékek jelölik a hiányzó cellákat
# nem kor hazas
# 0 False False False
# 1 False False False
# 2 False False True
# 3 False False True
pd.notnull(df3) # ugyan ez csak fordítva
print(df3.dropna()) # törli azokat a sorokat, amiknél van NaN érték valamelyik oszlopban
# alapértelmezetten nem változtatja meg a változó tartalmát,
# de ha az inplace paraméterét igazra állítjuk, akkor már igen
# a "subset" opcionális paraméterével megadható az is, hogy melyik
# oszlopkat nézze (ha nincs megadva, mindet)
# nem kor hazas
# 0 ferfi 23 True
# 1 no 32 False
print(df3.dropna(axis=1)) # törli azokat az oszlopokat, amiknél van NaN érték valamelyik sorban
# inplace paraméter itt is ugyan úgy működik
# nem kor
# 0 ferfi 23
# 1 no 32
# 2 no 42
# 3 ferfi 19
df3["hazas"].fillna(True,inplace = True) # A NaN értékek feltöltése a "hazas" oszlopban úgy,
# hogy a változtatások mentődnek a df3 változóba
print(df3) # nem kor hazas
# 0 ferfi 23 True
# 1 no 32 False
# 2 no 42 True
# 3 ferfi 19 True
Adatok módosítása¶
df3["hazas"].replace(True,"hazas") # A "hazas" oszlopban a True értékek módosítása a "hazas" szóra
df3["hazas"].replace(False,"nem hazas")
#vagy egyszerre, úgy hogy változzon df3 értéke
df3["hazas"].replace([True,False],["hazas","nem hazas"], inplace= True)
print(df3) # nem kor hazas
# 0 ferfi 23 hazas
# 1 no 32 nem hazas
# 2 no 42 hazas
# 3 ferfi 19 hazas
df3.rename(columns ={"hazas" : "hazas-e"}, inplace = True) # Oszlop átnevezése
Szűrés, rendezés, groupby¶
df3[df3["kor"] > 30] # boolean szűrés, akár több kifejezést is összekapcsolhatunk & és | jelekkel
df3.sort_values("kor") # értékek rendezése a megadott oszlop szerint, alapértelemzetten növekvő sorrendben
# nem kor hazas
# 3 ferfi 19 hazas
# 0 ferfi 23 hazas
# 1 no 32 nem hazas
# 2 no 42 hazas
df3.sort_values(["kor","hazas-e"], ascending = [False,True]) # rendezés több oszlop alapján csökkenő és növekvő sorrendben
group = df3.groupby("hazas-e") # groupby egy oszlop szerint
group.describe() # kor
# count mean std min 25% 50% 75% max
# hazas-e
# hazas 3.0 28.0 12.288206 19.0 21.0 23.0 32.5 42.0
# nem hazas 1.0 32.0 NaN 32.0 32.0 32.0 32.0 32.0
Mentés¶
Alternatívák¶
Dask¶
Bár az API sokkal szegényesebb, alternatíva lehet olyan esetekben, amikor a feldolgozandó adat nem fér bele a memóriába. A model különlegessége az, hogy semmit nem számol addig, ameddig meg nem kérjük rá külön a compute() függvényével. Így pl. két nagy adatbázis összefűzésénél nem próbálja meg egyből elmenteni az eredményt, ha utána amúgy is csak egy része érdekelne minket. Teljesítmény szempontjából rosszabb mint a pandas, viszont ha nem fér bele a memóriába az adat, akkor a pandas nem tud vele mit kezdeni.
PySpark¶
Főleg olyan esetekben használják, amikor több gépre osztanak le valamilyen műveletet. Hasonló teljesítménye van mint az előző modulnak, ha belefér a memóriába az adat, akkor még mindig a pandas nyer.
Vaex¶
Bár kevesebb funkciót támogat mint a pandas, az alap (pl. összefésülés, rendezés) feladatokat hasonló sebességgel vagy gyorsabban végzi el.
Matplotlib¶
Matplotlib¶
A NumPy modul egy kiegészítése, amivel grafikonokat rajzolhatunk ki (matlab-hoz hasonló módon). Nekünk a pyplot API lesz belőle csak fontos amit a matplotlib.pyplot modul importálásával érhetünk el.
Plot¶
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0,10]) # ezek lehetnének akár sima python listák is, ugyan úgy működik
y = np.array([0,40])
plt.plot(x,y) # a pontok megjelenítése
# egy pont az (x[i], y[i]) koordináta-párból jön létre,
# így jelen esetben egy (0,0) és egy (10,40) pontból áll az egyenes
plt.show() # a grafikon megjelenítse
Ha a show függvényhívás előtt többször is meghívjuk a plot függvényt, akkor több egyenest is rajzolhatunk ugyan arra az ábrára. Alapértelmezetten összeköti a pontokat, de a plot függvény 3. paraméterében ezt meg tudjuk változtatni, ahogy a pontok formáját és színét is. Pl.:
plt.plot(y,x)
plt.plot(x,y,'x--r') # [forma][vonal][szín] formátum
# (jelen esetben x forma, szaggatott vonal, piros szín)
# ha a vonal helyére nem írunk semmit, akkor csak a pontokat fogja kirajzolni,
# nem köti össze
plt.show()
Az összes formátum megtalálható a modul dokumentációjában (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot lap alja).
Feliratok¶
plt.plot(x,y)
plt.title("Title") # A diagram címe
plt.xlabel("x") # Tengelyfeliratok
plt.ylabel("y")
plt.show()
Több grafikon egyszerre¶
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0,10,20,30])
y = np.array([0,40,70,10])
plt.subplot(1,2,1)
plt.plot(x,y,'r')
x = np.array([0,1,2,3])
y = np.array([0,10,-20,30])
plt.subplot(1,2,2)
plt.plot(x,y)
plt.show()
A subplot függvénynek 3 paramétere van. Az első az, hogy a grafikonok hány sorban lesznek, a második, hogy hány oszlopban és a harmadik, hogy a következőnek kirajzolt grafikon hanyadik a sorban. Így pl. ha 6 ábrát szeretnénk egyszerre kirajzolni, mondjuk egy 2x3-as elrendezésben, akkor az első grafikon kirajzolása előtt meghívjuk a subplot függvényt (2,3,1) paraméterezéssel, majd a következőnél (2,3,2), stb.
Scatter¶
A scatter függvény segítségével is hasonló ábrákat rajzolhatunk, viszont itt biztosan nincsenek összekötve a pontok, illetve egyesével változtathatjuk minden pont színét.
import matplotlib.pyplot as plt
import numpy as np
x = np.array([11, 1, 0, 3, 13, 13, 2, 5, 10, 4])
y = np.array([23, 25, 37, 21, 20, 23, 22, 33, 32, 28])
plt.scatter(x,y)
x = np.array([14, 6, 10, 2, 0, 11, 10, 12, 0, 12])
y = np.array([28, 35, 7, 21, 12, 0, 17, 27, 18, 27])
colors = np.array(["red","green","blue","yellow","pink","black","orange","purple","beige","brown"])
plt.scatter(x,y, color = colors)
plt.show()
Bar¶
A bar függvénnyel tudunk oszlopdiagrammokat készíteni. Ennek a paraméterezése azzal tér el, hogy az első paraméterben szereplő lista most az oszlopok címe lesz.
import matplotlib.pyplot as plt
import numpy as np
x = np.array(["A","B","C","D","E"]) # Címkék
y = np.array([3,2,4,5,1]) # Oszlopok értékei
plt.bar(x,y, color = "red") # A color paraméteren keresztül ugyan úgy színezhető
plt.show()
Histogram¶
Egyetlen listát vár paraméterként, amiből kirajzol egy hisztogrammot.
import matplotlib.pyplot as plt
import numpy as np
x = np.random.normal(200,20,300) # 300 normál eloszlású szám generálása 200-as átlaggal, 10-es szórással
plt.hist(x)
plt.show()
Pie¶
Kördiagram készítésére használt függvény.
import matplotlib.pyplot as plt
import numpy as np
x = np.array([39,21,13,27])
labels = ["Kutya","Cica","T-Rex","lorem ipsum"]
colors = ["red","blue","green","orange"]
plt.pie(x, labels = labels, colors = colors)
plt.show()
Egy körcikk kiemelése¶
import matplotlib.pyplot as plt
import numpy as np
x = np.array([39,21,13,27])
labels = ["Kutya","Cica","T-Rex","lorem ipsum"]
colors = ["red","blue","green","orange"]
explode = [0,0.2,0,0] # a 0-nál nagyobb értékkel rendelkező körcikkek lesznek kiemelve
# jelen esetben mivel ez a második indexű, így a
# 21 értékű, "Cica" felírat kék körcikk lesz ez
plt.pie(x, labels = labels, colors = colors, explode = explode)
plt.show()
Feladatok¶
-
Készítsd el a foo függvényt, ami 2 mátrixot és egy string-et vár paraméterként. Ellenőrizd le, hogy a két mátrix alakja ugyan olyan. Ha nem, alaktísd át az egyiket (ha azonos elemszámúak akkor az elsőt, amúgy a nagyobbat) úgy, hogy megegyezzen az elemszámuk (a nagyobbat alakítsd vektorrá és vágd le a végét) és az alakuk is. A függvény a két mátrix elemenkénti szorzatával térjen vissza.
-
Olvasd be a data1.csv és data2.csv fájlokat egy-egy változóba. Fűzd össze a két fájl tartalmát (a második fájl utolsó oszlopa nem egyezik meg az első fájl utolsó oszlopával, így először nevezd át a DataFrame-en belül). Töröld ki azokat a sorokat, ahol az "ip_address" oszlop üres. Töltsd ki a "gender" oszlop üres sorait úgy, hogy mindenhova az "Attack Helicopter" szó kerüljön. Végül mentsd el a táblázatot "res.csv" néven.
-
Az említett függvények további opcionális paramétereinek áttekintése (pl. a bar függvénynél a width).
-
MOAÁ (Mother of All Ábrák) Készíts el egy ábrát, amin az összes tanult grafikon szerepel (egymás mellett/alatt valamilyen elrendezésben). A felhasznált adatok és címkék szabadon választhatóak, de legyenek valami értelmes mennyiségben (ne 3 érték szerepeljen egy hisztogrammon). Ezen kívül még mindegyik grafikont kirajzoló függvénynek használd legalább 2 opcionális paraméterét (pl. szín, vastagság, stb).