numpy je paket (modul) za (efikasno) numeričko računanje u Pythonu. Naglasak je na efikasnom računanju s nizovima, vektorima i matricama, uključivo višedimenzionalne stukture. Napisan je u C-u i Fortanu te koristi BLAS biblioteku.
In [21]:
from numpy import *
In [22]:
v = array([1,2,3,4])
v
Out[22]:
In [23]:
M = array([[1, 2], [3, 4]])
M
Out[23]:
In [24]:
type(v), type(M)
Out[24]:
In [25]:
v.shape
Out[25]:
In [26]:
M.shape
Out[26]:
In [27]:
v.size, M.size
Out[27]:
Možemo koristiti i funkcije numpy.shape, numpy.size
In [28]:
shape(M)
Out[28]:
In [29]:
size(M)
Out[29]:
Koja je razlika između numpy.ndarray tipa i standardnih lista u Pythonu?
numpy.ndarraynumpy.ndarray nisu dinamički objekti: pri kreiranju im je određen tipnumpy.ndarray implementirane su razne efikasne metode važne u numericidtype (data type) nam daje informaciju o tipu podataka u nizu:
In [30]:
M.dtype
Out[30]:
Kako je M statički objekt, ne možemo napraviti ovo:
In [31]:
M[0,0] = "hello"
Naravno, ovo je ok:
In [32]:
M[0,0]=5
dtype se može eksplicitno zadati:
In [33]:
M = array([[1, 2], [3, 4]], dtype=complex)
M
Out[33]:
Tipično dtype su: int, float, complex, bool, object, itd.
Ali možemo biti i eksplicitni vezano za veličinu registra: int64, int16, float128, complex128.
In [34]:
x = arange(0, 10, 1) # argumenti: početak, kraj, korak
x # 10 nije u nizu!
Out[34]:
In [35]:
x = arange(-1, 1, 0.1)
x
Out[35]:
In [36]:
# ovdje su i početak i kraj uključeni!
linspace(0, 10, 25)
Out[36]:
In [37]:
logspace(0, 10, 10, base=e)
Out[37]:
In [38]:
x, y = mgrid[0:5, 0:5] # slično kao meshgrid u MATLAB-u
In [39]:
x
Out[39]:
In [40]:
y
Out[40]:
In [41]:
from numpy import random
In [42]:
# uniformna distribucija na [0,1]
random.rand(5,5)
Out[42]:
In [43]:
# standardna normalna distribucija
random.randn(5,5)
Out[43]:
In [44]:
# dijagonalna matrica
diag([1,2,3])
Out[44]:
In [45]:
# matrica sa sporednom dijagonalom
diag([1,2,3], k=1)
Out[45]:
In [46]:
zeros((3,3))
Out[46]:
In [47]:
ones((3,3))
Out[47]:
Često učitavamo podatke iz datoteka (lokalno ili s weba). Važni formati su cvs (comma-separated values) i tsv (tab-separated values).
In [48]:
!head tpt-europe.csv
In [49]:
data = genfromtxt('tpt-europe.csv')
In [50]:
data.shape, data.dtype
Out[50]:
Uz numpy.savetxt možemo napraviti i obrnuto.
In [51]:
M = random.rand(3,3)
M
Out[51]:
In [52]:
savetxt("random-matrix.csv", M)
In [53]:
!cat random-matrix.csv
In [54]:
savetxt("random-matrix.csv", M, fmt='%.5f') # s fmt specificiramo format
!cat random-matrix.csv
Postoji i interni format za numpy nizove:
In [55]:
save("random-matrix.npy", M)
!file random-matrix.npy
In [56]:
load("random-matrix.npy")
Out[56]:
In [57]:
M.itemsize # byte-ovi po elementu
Out[57]:
In [58]:
M.nbytes
Out[58]:
In [59]:
M.ndim
Out[59]:
Indeksiranje funkcionira standardno.
In [60]:
v[0]
Out[60]:
In [61]:
M[1,1]
Out[61]:
In [62]:
M
Out[62]:
In [63]:
M[1]
Out[63]:
Naravno, možemo koristiti i : operator:
In [64]:
M[1,:] # redak 1
Out[64]:
In [65]:
M[:,1] # stupac 1
Out[65]:
In [66]:
M[1,:] = 0
M[:,2] = -1
In [67]:
M
Out[67]:
In [68]:
A = array([1,2,3,4,5])
A
Out[68]:
In [69]:
A[1:3]
Out[69]:
In [70]:
A[1:3] = [-2,-3]
A
Out[70]:
In [71]:
A[::]
Out[71]:
In [72]:
A[::2]
Out[72]:
In [73]:
A[:3]
Out[73]:
In [74]:
A[3:]
Out[74]:
S negativnim indeksima računamo od kraja niza:
In [75]:
A = array([1,2,3,4,5])
In [76]:
A[-1] # zadnji element niza
Out[76]:
In [77]:
A[-3:] # zadnja tri elementa
Out[77]:
Naravno, iste operacije imamo i za višedimenzionalne nizove.
In [78]:
A = array([[n+m*10 for n in range(5)] for m in range(5)])
A
Out[78]:
In [79]:
A[1:4, 1:4]
Out[79]:
In [80]:
A[::2, ::2]
Out[80]:
In [81]:
indeksi_redaka = [1, 2, 3]
A[indeksi_redaka]
Out[81]:
In [82]:
indeksi_stupaca = [1, 2, -1]
A[indeksi_redaka, indeksi_stupaca]
Out[82]:
Možemo koristiti i tzv. maske: ako je maska numpy niz tipa bool, tada se izabiru oni elementi koji u maski odgovaraju vrijednosti True.
In [83]:
B = array([n for n in range(5)])
B
Out[83]:
In [84]:
maska = array([True, False, True, False, False])
B[maska]
Out[84]:
In [85]:
maska = array([1,0,1,0,0], dtype=bool)
B[maska]
Out[85]:
Zanimljiviji primjer:
In [86]:
x = arange(0, 10, 0.5)
x
Out[86]:
In [87]:
maska = (5 < x) * (x < 7.5)
maska
Out[87]:
In [88]:
x[maska]
Out[88]:
In [89]:
indeksi = where(maska)
indeksi
Out[89]:
In [90]:
x[indeksi]
Out[90]:
In [91]:
print(A)
diag(A)
Out[91]:
In [92]:
diag(A, -1)
Out[92]:
In [93]:
v2 = arange(-3,3)
v2
Out[93]:
In [94]:
indeksi_redaka = [1, 3, 5]
v2[indeksi_redaka]
Out[94]:
In [95]:
v2.take(indeksi_redaka)
Out[95]:
U sljedećem primjeru take djeluje na listu, a izlaz je array:
In [96]:
take([-3, -2, -1, 0, 1, 2], indeksi_redaka)
Out[96]:
Funkcija choose:
In [97]:
koji = [1, 0, 1, 0]
izbori = [[-1,-2,-3,-4], [5,4,3,2]]
choose(koji, izbori)
Out[97]:
Što radi ova funkcija?
In [98]:
v1 = arange(0, 5)
In [99]:
v1 * 2
Out[99]:
In [100]:
v1 + 2
Out[100]:
In [101]:
print(A)
A * 2, A + 2
Out[101]:
Defaultne operacije na nizovima su uvijek definirane po elementima.
In [102]:
A * A
Out[102]:
In [103]:
v1 * v1
Out[103]:
In [104]:
A.shape, v1.shape
Out[104]:
In [122]:
print(A,v1)
A * v1
Out[122]:
Kako doći do standardnog umnoška?
In [123]:
dot(A, A)
Out[123]:
In [124]:
A @ A # nova operacija definirana u Python-u 3.5+
Out[124]:
In [125]:
matmul(A,A) # @ je zapravo pokrata za matmul, dot i matmul nisu iste operacije (poklapaju se na 1D i 2D nizovima)
Out[125]:
In [126]:
dot(A, v1)
Out[126]:
In [127]:
A @ v1
Out[127]:
In [128]:
v1 @ v1 # analogno dot(v1, v1)
Out[128]:
Matrice mogu biti i višedimenzionalne
In [129]:
a = random.rand(8,13,13)
b = random.rand(8,13,13)
matmul(a, b).shape
Out[129]:
Postoji i tip matrix. Kod njega operacije +, -, * se ponašaju onako kako smo navikli.
In [130]:
M = matrix(A)
v = matrix(v1).T # da bi dobili stupčasti vektor
In [131]:
v
Out[131]:
In [132]:
M*M
Out[132]:
In [133]:
M*v
Out[133]:
In [134]:
# skalarni produkt
v.T * v
Out[134]:
In [135]:
v + M*v
Out[135]:
Naravno, dimenzije trebaju biti kompatibilne.
In [136]:
v = matrix([1,2,3,4,5,6]).T
In [137]:
shape(M), shape(v)
Out[137]:
In [138]:
M * v
Još neke funkcije: inner, outer, cross, kron, tensordot.
In [139]:
C = matrix([[1j, 2j], [3j, 4j]])
C
Out[139]:
In [140]:
conjugate(C)
Out[140]:
Adjungiranje:
In [141]:
C.H
Out[141]:
Za izvlačenje realnog, odnosno imaginarnog dijela: real i imag:
In [142]:
real(C) # isto što i C.real
Out[142]:
In [143]:
imag(C) # isto što i C.imag
Out[143]:
In [144]:
angle(C+1) # u MATLAB-u je to funkcija arg, dakle argument (faza) kompleksnog broja
Out[144]:
In [145]:
abs(C)
Out[145]:
In [146]:
from numpy.linalg import inv, det
inv(C) # isto što i C.I
Out[146]:
In [147]:
C.I * C
Out[147]:
In [148]:
det(C)
Out[148]:
In [149]:
det(C.I)
Out[149]:
In [150]:
# u stockholm_td_adj.dat su podaci o vremenu za Stockholm
dataStockholm = genfromtxt('stockholm_td_adj.dat')
dataStockholm.shape
Out[150]:
In [151]:
# temperatura se nalazi u 4. stupcu (znači stupcu broj 3)
mean(dataStockholm[:,3])
Out[151]:
Prosječna dnevna temperatura u Stockholmu u zadnjiih 200 godina je bila 6.2 C.
In [152]:
std(dataStockholm[:,3]), var(dataStockholm[:,3])
Out[152]:
In [153]:
dataStockholm[:,3].min()
Out[153]:
In [154]:
dataStockholm[:,3].max()
Out[154]:
In [155]:
d = arange(0, 10)
d
Out[155]:
In [156]:
sum(d)
Out[156]:
In [157]:
prod(d+1)
Out[157]:
In [158]:
# kumulativa suma
cumsum(d)
Out[158]:
In [159]:
# kumulativan produkt
cumprod(d+1)
Out[159]:
In [160]:
# isto što i: diag(A).sum()
trace(A)
Out[160]:
Naravno, sve ove operacije možemo raditi na dijelovima nizova.
In [161]:
!head -n 3 stockholm_td_adj.dat
Format je: godina, mjesec, dan, prosječna dnevna temperatura, najniža, najviša, lokacija.
Recimo da nas zanimaju samo temperature u veljači.
In [162]:
# mjeseci su 1.,..., 12.
unique(dataStockholm[:,1])
Out[162]:
In [163]:
maska_velj = dataStockholm[:,1] == 2
In [164]:
mean(dataStockholm[maska_velj,3])
Out[164]:
Sada nije problem doći do histograma za prosječne mjesečne temperature u par redaka.
In [165]:
mjeseci = arange(1,13)
mjeseci_prosjek = [mean(dataStockholm[dataStockholm[:,1] == mjesec, 3]) for mjesec in mjeseci]
from pylab import *
%matplotlib inline
fig, ax = subplots()
ax.bar(mjeseci, mjeseci_prosjek)
ax.set_xlabel("Mjesec")
ax.set_ylabel("Prosj. mj. temp.");
In [166]:
m = rand(3,3)
m
Out[166]:
In [167]:
m.max()
Out[167]:
In [168]:
# max u svakom stupcu
m.max(axis=0)
Out[168]:
In [169]:
# max u svakom retku
m.max(axis=1)
Out[169]:
Oblik niza se može promijeniti bez da se dira memorija, dakle mogu se primijenjivati i na veliku količinu podataka.
In [170]:
A
Out[170]:
In [171]:
n, m = A.shape
In [172]:
B = A.reshape((1,n*m))
B
Out[172]:
In [173]:
B[0,0:5] = 5 # promijenili smo B
B
Out[173]:
In [174]:
A # a time smo promijenili i A
Out[174]:
Funkcija flatten radi kopiju.
In [175]:
B = A.flatten()
B
Out[175]:
In [176]:
B[0:5] = 10
B
Out[176]:
In [177]:
A # A je sad ostao isti
Out[177]:
In [178]:
v = array([1,2,3])
In [179]:
shape(v)
Out[179]:
In [180]:
# pretvorimo v u matricu
v[:, newaxis]
Out[180]:
In [181]:
v[:,newaxis].shape
Out[181]:
In [182]:
v[newaxis,:].shape
Out[182]:
In [183]:
a = array([[1, 2], [3, 4]])
In [184]:
# ponovimo svaki element tri puta
repeat(a, 3)
Out[184]:
In [185]:
tile(a, 3)
Out[185]:
In [186]:
b = array([[5, 6]])
In [187]:
concatenate((a, b), axis=0)
Out[187]:
In [188]:
concatenate((a, b.T), axis=1)
Out[188]:
In [189]:
vstack((a,b))
Out[189]:
In [190]:
hstack((a,b.T))
Out[190]:
In [191]:
A = array([[1, 2], [3, 4]])
A
Out[191]:
In [192]:
# B je isto što i A (bez kopiranja podataka)
B = A
Ako želimo napraviti novu kopiju, koristimo funkciju copy:
In [193]:
B = copy(A)
In [194]:
v = array([1,2,3,4])
for element in v:
print (element)
In [195]:
M = array([[1,2], [3,4]])
for row in M:
print ("redak {}".format(row))
for element in row:
print (element)
Funkcija enumerate nam daje i element i njegov indeks:
In [196]:
for row_idx, row in enumerate(M):
print ("indeks retka {} redak {}".format(row_idx, row))
for col_idx, element in enumerate(row):
print ("col_idx {} element {}".format(col_idx, element))
M[row_idx, col_idx] = element ** 2
In [197]:
def Theta(x):
"""
Sklarna verzija step funkcije.
"""
if x >= 0:
return 1
else:
return 0
In [198]:
Theta(array([-3,-2,-1,0,1,2,3]))
In [199]:
Theta_vec = vectorize(Theta)
In [200]:
Theta_vec(array([-3,-2,-1,0,1,2,3]))
Out[200]:
To smo mogli napraviti i ručno.
In [201]:
def Theta(x):
"""
Vektorska verzija step funkcije.
"""
return 1 * (x >= 0)
In [202]:
Theta(array([-3,-2,-1,0,1,2,3]))
Out[202]:
In [203]:
# radi naravno i za skalare
Theta(-1.2), Theta(2.6)
Out[203]:
In [204]:
M
Out[204]:
In [205]:
if (M > 5).any():
print ("barem jedan element iz M je veći od 5")
else:
print ("svi elementi iz M su manji ili jednaki od 5")
In [206]:
if (M > 5).all():
print ("svi elementi iz M su veći od 5")
else:
print ("barem jedan element je manji ili jednak od 5")
Eksplicitno pretvaranje podataka. Uvijek stvara novi niz.
In [207]:
M.dtype
Out[207]:
In [208]:
M2 = M.astype(float)
M2
Out[208]:
In [209]:
M2.dtype
Out[209]:
In [210]:
M3 = M.astype(bool)
M3
Out[210]:
In [211]:
from verzije import *
from IPython.display import HTML
HTML(print_sysinfo()+info_packages('numpy,matplotlib'))
Out[211]:
A=random.randn(5,5). Izvucite $2\times 2$ matricu $B$ iz gornjeg desnog kuta matrice $A$. Pomnožite matricu $B$ s nekom drugom $2\times 2$ matricom te ubacite tu matricu u gornji lijevi kut matrice $A$.x = linspace(0, 1, 3)
# y = 2*x + 1:
y=x; y*=2; y+=1
# z = 4*x - 4:
z=x; z*=4; z-=4
print (x, y, z)
Izvršite ovaj kod. Objasnite zašto x, y i z imaju iste vrijednosti.f i broj n
te dva niza a,b a vraćati niz brojeva koji odgovaraju aproksimaciji integrala $\int_{a_i}^{b_i} f(x) dx$ trapeznom formulom.
In [ ]: