csomag | |
---|---|
NumPy | Hatékony N-dimenziós tömb |
SciPy | Numerikus számÃtások |
Matplotlib | Grafikonok és rajzok |
IPython (Jupyter) | InteraktÃv notebook |
SymPy | Szimbolikus számÃtások |
Pandas | Adatbányászat |
A Python Scientific stack (és sok más) alap modulja.
A Mandelbrot-halmaz azon $c$ komplex számokból áll, melyekre az alábbi $x_{n}$ rekurzÃv sorozat:
$x_{1}=c$
$x_{n+1}:=(x_{n})^{2}+c$
nem tart végtelenbe, azaz abszolút értékben (hosszára nézve) korlátos.
import numpy as np
¶import numpy as np
A numpy központi objektuma az ndarray
($n$-dimenziós tömb).
A = np.array([[1, 2], [3, 4], [5, 6]])
A
type(A)
A.shape
egy tuple a tömb dimenzióival, alakjával.
A.shape
Többdimenziós tömbökkel sok helyen találkozhatunk. Egyik tipikus megjelenésük a képek tárolása. Minden tömb egy háromdimenziós tömb, ahol az első két dimenzió az x és y koordinátának felel meg, a harmadik mentén pedig felsoroljuk az RGB értékeket. Az RGB értékek 0 és 255 közötti egészek.
import imageio #kép beolvasáshoz
import matplotlib.pyplot as plt #kép megjelenÃtéshez
fig_size = plt.rcParams["figure.figsize"] #kép méret növelése
fig_size[0] = 10
fig_size[1] = 8
plt.rcParams["figure.figsize"] = fig_size
dragon = imageio.imread('dragon.jpg')
print(type(dragon))
dragon.shape, dragon.dtype
dragon[0,0]
plt.imshow(dragon)
plt.show()
A listákkal ellentétben nem tárolhatunk benne bármit!
A dtype
megadja a tárolt elemek tÃpusát
A.dtype
a=10**30 #Ez sima ügy
#A[0,0]=10**30 #Ez túl nagy lenne
A = np.array([1.5, 2])
A.dtype
Megadhatjuk a dtype
-ot amikor létrehozzuk a tömböt.
np.array(['10', '20'], dtype="float32")
T = np.array(['körte', 'alma'])
print(T)
print(T.shape, T.dtype, type(T))
Fix hosszúságú karakter tömböket tárol!!
T[1] = "banana"
T
A = np.array([[1, 2], [3, 4], [5, 6]])
A
A[0], A[1]
A[:, 0]
A[2][1], A[2, 1], type(A[2, 1])
A = np.array([[1, 2], [3, 4], [5, 6]])
A
A[:2] # vagy A[:2, :]
A[:, 1:]
A[::2]
B = np.array([[[1, 2, 3],[4, 5, 6]]])
B.shape, B.ndim
B
B[0].shape
B[0, 1], B[0, 1].shape
B[0, 1, 2]
A = np.array([[1, 2], [3, 4], [5, 6]])
print(A)
A + A
A * A
print(np.exp(A))
print(np.sin(A*np.pi/6))
print(2**A)
print(1/A)
A=np.array([1,1,1,0]) & np.array([1,0,1,1])
A
A=np.array([1,1,1,0]) | np.array([1,0,1,1])
A
A = np.array([[1, 3], [2, 4]])
P = (A >= 2)
print(P)
print(P.dtype)
Egy listával vagy tömbbel fogjuk megadni, hogy hanyadik elemeket szeretnénk.
B = np.array(["a","b","c","d","e","f","g"])
np.array([B[0],B[3],B[4],B[6]])
B[[0,3,4,6]] #gyorsabban ugyanaz
B[np.array([0,3,4,6])] #tömbbel ugyanaz
Több dimenzióban komplikálódnak a dolgok.
Ha egyetlen index tömbbel indexelünk, annak elemei megfelelnek M első kordináta szerint vett elemeinek.
M = np.arange(12).reshape(3,4)
M
np.array([[M[0],M[1]],[M[2],M[2]]])
M[np.array([[0,1],[2,2]])] #gyorsabban ugyanaz
Ha több index tömbbel indexelünk, akkor az első az első koordinátnak a második a másodiknak, ... felel meg.
np.array([M[0][2],M[1][2],M[1][0]])
np.array([M[0,2],M[1,2],M[1,0]])
M[np.array([0,1,1]),np.array([2,2,0])] #gyorsabban ugyanaz
np.array([[M[0,1],M[1,0]],[M[2,1],M[2,3]]])
M[np.array([[0,1],[2,2]]),np.array([[1,0],[1,3]])] #gyorsabban ugyanaz
M[:,[1,3]]
M[[1,2],:]
Többször is kiválaszthatjuk ugyanazt a sort vagy oszlopot:
M[[2,1,2],:]
Többdimenzióban még komplikáltabba a helyzet. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
A reshape
függvénnyel megváltoztathatjuk a tömb alakját anélkül, hogy a tartalmazott elemek megváltoznának, vagy akár lemásolódnának a hattérben.
B = np.array([[[1, 2, 3], [4, 5, 6]]])
B.reshape((2, 3))
B.reshape((3, 2))
ValueError
hibát kapunk ha rosz alakot adunk meg.
#B.reshape(7) # raises ValueError
np.array(range(6)).reshape((1, 2, 3))
Ha -1
-et adunk meg, megpróbálja kitalálni, hogy annak a dimenziónak mekkorának kell lennie az elemek száma alapján.
X = np.array(range(12)).reshape((2, -1, 2))
print("X.shape:", X.shape)
print(X)
A resize
akkor is működik, ha az elemek száma nem passzol. Ilyenkor töröl, vagy feltölt nullákkal. Magát a tömböt változtatja meg.
X = np.array([[1, 2], [3, 4]])
X.resize((5, 3))
X.resize((1, 2))
X
Ritkán akarjuk egyesével megadni az elemeket, ezért van egy csomó gyorsabb módszer:
arange
: range megfelelője csak nem listát hoz létre, hanem tömböt.linspace
: egyenletesen felosztott intervallumones
, ones_like
, csupa egyeszeros
, zeros_like
, csupa nullaeye
: indetitás mátrix 2 dimenzióbanfromfunction
függvény alapjánAz np.ones_like()
és np.zeros_like()
függvények megtartják a formát és a dtype
-ot!
np.arange(10), np.arange(10).shape
np.arange(1, 21, 2).reshape(5, -1)
np.linspace(0, 4, 11)
np.ones((3, 2))
np.zeros((2, 3, 2))
A = np.arange(6).reshape(3, -1)
np.zeros_like(A)
np.eye(5)
np.eye(4, dtype=bool)
Az egyik leghasznosabb, hogy az indexek függvényében is definiálhatjuk a tömböt:
np.fromfunction(lambda i, j: i == j, (3, 3))
np.fromfunction(lambda i,j: 100*i+j, (5,5))
Bármelyik dimenzió szerint ragaszthatunk, ha megfelelőek a dimenziók.
A = np.arange(8).reshape(2, -1)
B = np.arange(8).reshape(2, -1)
np.concatenate((A, B), axis=0)
np.concatenate((A, B), axis=-1) # utolsó dimenzió dimension
Mivel általában az elsÅ‘ vagy második koordináta szerint ragasztunk, ezekre vannak rövidÃtések:
A = np.arange(6).reshape(2, -1)
B = np.arange(8).reshape(2, -1)
np.hstack((A, B))
A = np.arange(6).reshape(-1, 2)
B = np.arange(8).reshape(-1, 2)
print(A.shape, B.shape)
np.vstack((A, B))
plt.imshow(np.vstack((dragon,dragon)))
plt.show()
plt.imshow(np.hstack((dragon,dragon)))
plt.show()
np.stack
egy új dimenzió szerint egymás mellé rakja a tömböket
plt.imshow(np.stack((dragon[:,:,0],dragon[:,:,0],dragon[:,:,0] ),axis=2 ))
plt.show()
Alapból az első koordináta szerint van iterálás:
A = np.arange(6).reshape(2, -1)
for row in A:
print(row)
De természetesen csinálhatunk ilyet:
B = np.arange(6).reshape(1, 2, 3)
for x in B[0, 0, :]:
print(x)
És végigiterálhatunk az összes elemen is:
for a in B.flat:
print(a)
Különböző méretű tömbökkel is tudunk műveleteket végrehajtani, ha az alakjaik megfelelnek néhány feltételnek.
Például egy $1\times 1$-es tömb összesorozható egy több dimenziós tömbbel, mintha skalárral szoroznánk.
s = 2.0 * np.ones((1, 1))
A=np.arange(12).reshape(3,4)
print(s)
print(A)
s * A
De különböző méretű tömbökön nem tudunk elemenkénti műveletet végrehajtani:
# np.ones((2,3)) + np.ones((3,2))
Azt, hogy mi történjen a broadcasting határozza meg. Ha valamelyik dimenzió mérete 1, akkor akkor az a dimenzió brodacastolható , azaz olyan széles lehet a dimenzió, amit a művelet akar.
np.arange(3).reshape((1,3)) + np.zeros((2, 3))
np.arange(3).reshape((3,1)) + np.zeros((3, 4))
Több dimenzió egyszerre is broadcastolható:
np.arange(3).reshape((1,3,1)) + np.zeros((2,3,5))
Ha mondjuk egy array alakja (1,3,1)
akkor az első és a harmadik dimenzió broadcastolható. Ekkor egy [x,y,z]
index hármast [0,y,0]
-ként értelmez a Python. Tehát a broadcastolt dimenziókban 0-nak tekintjük az indexet.
Nem létezÅ‘ dimenziókat is broadcastolhatunk, Ãgy lehet, hogy egy egydimenziós tömb összeadható egy két vagy háromdimenzióssal. Ekkor a hiányzó dimenziót elfelejtjük. Például egy ha az két tömb alakja (k,)
és (i, j, k)
és összadjuk őket akkor az (a,b,c)
indexből (c)
lesz. Tehát a kamu dimenziókat előre szúrjuk be.
def test_broadcast(x, y):
try:
A = np.ones(x) + np.ones(y)
print("Broadcastolható")
except ValueError:
print("Nem broadcastolható")
test_broadcast((3), (3,2,2))
test_broadcast((2), (3,2,2))
test_broadcast((3,1,4), (3,2,1))
test_broadcast((3,1,4), (3,2,2))
Meg is mondhatjuk, hogy hol hozzon létre új dimenziókat, a none
kulcsszóval.
(np.ones(3)[:, None, None] + np.ones((3,2,2)))
Tehát ekkor Ãgy változnak a dimenziók: (3, None, None) + (3, 2, 2) = (3, 2, 2)
Rács a komplex számsÃkon:
np.arange(5)[:, None] + 1j * np.arange(5)[None, :]
Tengely menti szummázás:
Y = np.arange(24).reshape(2,3,4)
Y
Y.sum() # összes elem összege
Y.sum(axis=0)
Y.sum(axis=1)
mean, std, var
hasonlóan működik az átlag, szórás és szórásnégyzet kiszámolására.
Y.mean(),Y.std(),Y.var()
Y.mean(axis=(0, 2))
Feltételnek megfelelő elemek kiválasztása:
A = np.random.random((4, 3))
print(A.mean())
A
Az átlagnál nagyobb elemek:
A[A > A.mean()]
A > A.mean()
np.where
visszatér azokkal a tömbökkel, amik a speckó indexeléshez kellenek, ha a feltételnek megfelelő elemeket akarjuk:
np.where(A > A.mean())
A[np.where(A > A.mean())]
A Mandelbrot-halmaz azon $c$ komplex számokból áll, melyekre az alábbi $x_{n}$ rekurzÃv sorozat:
$x_{1}=c$
$x_{n+1}:=(x_{n})^{2}+c$
nem tart végtelenbe, azaz abszolút értékben (hosszára nézve) korlátos.
import matplotlib.pyplot as plt #rajzoláshoz
def mandelbrot( h,w, maxit=20 ):
c=(np.linspace(-1.4,1.4,h))[:, None]*1j + (np.linspace(-2,0.8,w))[None, :]
z = c
divtime = maxit + np.zeros(z.shape, dtype=int)
for i in range(maxit):
z = z**2 + c
diverge = z*np.conj(z) > 2**2 # Ki divergál?
div_now = diverge & (divtime==maxit) # Ki divergál ebben a lépésben?
divtime[div_now] = i # felÃrjuk, hogy mikor divergált
z[diverge] = 2 # ne divárgáljunk túl sokat
return divtime
# a többi a rajzoláshoz kell, most nem fontos
fig = plt.figure(figsize = (10,10))
ax = fig.add_subplot(111)
ax.imshow(mandelbrot(1000,1000), interpolation='none')
plt.show()