Numpy

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 *

Kreiranje nizova pomoću numpy modula

In [22]:
v = array([1,2,3,4])
v
Out[22]:
array([1, 2, 3, 4])
In [23]:
M = array([[1, 2], [3, 4]])
M
Out[23]:
array([[1, 2],
       [3, 4]])
In [24]:
type(v), type(M)
Out[24]:
(numpy.ndarray, numpy.ndarray)
In [25]:
v.shape
Out[25]:
(4,)
In [26]:
M.shape
Out[26]:
(2, 2)
In [27]:
v.size, M.size
Out[27]:
(4, 4)

Možemo koristiti i funkcije numpy.shape, numpy.size

In [28]:
shape(M)
Out[28]:
(2, 2)
In [29]:
size(M)
Out[29]:
4

Koja je razlika između numpy.ndarray tipa i standardnih lista u Pythonu?

  • liste u Pythonu mogu sadržavati bilo kakve vrste objekata, to nije slučaj s numpy.ndarray
  • numpy.ndarray nisu dinamički objekti: pri kreiranju im je određen tip
  • za numpy.ndarray implementirane su razne efikasne metode važne u numerici
  • de facto sva računanja se odvijaju u C-u i Fortranu pomoću BLAS rutina

dtype (data type) nam daje informaciju o tipu podataka u nizu:

In [30]:
M.dtype
Out[30]:
dtype('int64')

Kako je M statički objekt, ne možemo napraviti ovo:

In [31]:
M[0,0] = "hello"
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-31-a09d72434238> in <module>()
----> 1 M[0,0] = "hello"

ValueError: invalid literal for int() with base 10: '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]:
array([[ 1.+0.j,  2.+0.j],
       [ 3.+0.j,  4.+0.j]])

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.

Funkcije koje generiraju nizove

In [34]:
x = arange(0, 10, 1) # argumenti: početak, kraj, korak

x # 10 nije u nizu!
Out[34]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [35]:
x = arange(-1, 1, 0.1)
x
Out[35]:
array([ -1.00000000e+00,  -9.00000000e-01,  -8.00000000e-01,
        -7.00000000e-01,  -6.00000000e-01,  -5.00000000e-01,
        -4.00000000e-01,  -3.00000000e-01,  -2.00000000e-01,
        -1.00000000e-01,  -2.22044605e-16,   1.00000000e-01,
         2.00000000e-01,   3.00000000e-01,   4.00000000e-01,
         5.00000000e-01,   6.00000000e-01,   7.00000000e-01,
         8.00000000e-01,   9.00000000e-01])
In [36]:
# ovdje su i početak i kraj uključeni!
linspace(0, 10, 25)
Out[36]:
array([  0.        ,   0.41666667,   0.83333333,   1.25      ,
         1.66666667,   2.08333333,   2.5       ,   2.91666667,
         3.33333333,   3.75      ,   4.16666667,   4.58333333,
         5.        ,   5.41666667,   5.83333333,   6.25      ,
         6.66666667,   7.08333333,   7.5       ,   7.91666667,
         8.33333333,   8.75      ,   9.16666667,   9.58333333,  10.        ])
In [37]:
logspace(0, 10, 10, base=e)
Out[37]:
array([  1.00000000e+00,   3.03773178e+00,   9.22781435e+00,
         2.80316249e+01,   8.51525577e+01,   2.58670631e+02,
         7.85771994e+02,   2.38696456e+03,   7.25095809e+03,
         2.20264658e+04])
In [38]:
x, y = mgrid[0:5, 0:5] # slično kao meshgrid u MATLAB-u
In [39]:
x
Out[39]:
array([[0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [2, 2, 2, 2, 2],
       [3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4]])
In [40]:
y
Out[40]:
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])
In [41]:
from numpy import random
In [42]:
# uniformna distribucija na [0,1]
random.rand(5,5)
Out[42]:
array([[ 0.46634159,  0.18383259,  0.99043082,  0.95553566,  0.86117026],
       [ 0.18758889,  0.66275122,  0.88660117,  0.48603761,  0.58020297],
       [ 0.76289553,  0.66796829,  0.70291958,  0.84876206,  0.90293859],
       [ 0.62222178,  0.46259364,  0.86471336,  0.73420665,  0.21731253],
       [ 0.63499971,  0.49470533,  0.06818067,  0.85432396,  0.87013258]])
In [43]:
# standardna normalna distribucija
random.randn(5,5)
Out[43]:
array([[ 1.8841264 ,  1.79222299, -0.15896515, -0.95471483,  0.604597  ],
       [ 0.01879898, -0.21818353, -0.02871515, -0.17077362,  2.32474892],
       [ 0.47474772,  0.30405552, -0.37323118, -0.60411745,  1.06795274],
       [-0.2546505 , -0.10511935,  0.73920025,  2.50885605, -1.04196785],
       [ 0.2522967 , -0.87931277, -0.93793984, -0.71194124,  0.67464873]])
In [44]:
# dijagonalna matrica
diag([1,2,3])
Out[44]:
array([[1, 0, 0],
       [0, 2, 0],
       [0, 0, 3]])
In [45]:
# matrica sa sporednom dijagonalom
diag([1,2,3], k=1)
Out[45]:
array([[0, 1, 0, 0],
       [0, 0, 2, 0],
       [0, 0, 0, 3],
       [0, 0, 0, 0]])
In [46]:
zeros((3,3))
Out[46]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
In [47]:
ones((3,3))
Out[47]:
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

Učitavanje podataka

Č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
1850,-0.211
1851,-0.403
1852,0.334
1853,-0.762
1854,-0.019
1855,-0.961
1856,-0.243
1857,0.420
1858,-0.059
1859,0.018
In [49]:
data = genfromtxt('tpt-europe.csv')
In [50]:
data.shape, data.dtype
Out[50]:
((158,), dtype('float64'))

Uz numpy.savetxt možemo napraviti i obrnuto.

In [51]:
M = random.rand(3,3)
M
Out[51]:
array([[ 0.93875912,  0.43215004,  0.23129988],
       [ 0.13593153,  0.0413665 ,  0.21458492],
       [ 0.96261572,  0.22372779,  0.44478241]])
In [52]:
savetxt("random-matrix.csv", M)
In [53]:
!cat random-matrix.csv
9.387591161588458855e-01 4.321500444939530006e-01 2.312998801967627305e-01
1.359315283144698627e-01 4.136650288835774791e-02 2.145849165333063580e-01
9.626157155774026641e-01 2.237277861211310892e-01 4.447824126746069417e-01
In [54]:
savetxt("random-matrix.csv", M, fmt='%.5f') # s fmt specificiramo format

!cat random-matrix.csv
0.93876 0.43215 0.23130
0.13593 0.04137 0.21458
0.96262 0.22373 0.44478

Postoji i interni format za numpy nizove:

In [55]:
save("random-matrix.npy", M)

!file random-matrix.npy
random-matrix.npy: data
In [56]:
load("random-matrix.npy")
Out[56]:
array([[ 0.93875912,  0.43215004,  0.23129988],
       [ 0.13593153,  0.0413665 ,  0.21458492],
       [ 0.96261572,  0.22372779,  0.44478241]])
In [57]:
M.itemsize # byte-ovi po elementu
Out[57]:
8
In [58]:
M.nbytes
Out[58]:
72
In [59]:
M.ndim
Out[59]:
2

Rad s nizovima

Indeksiranje funkcionira standardno.

In [60]:
v[0]
Out[60]:
1
In [61]:
 M[1,1]
Out[61]:
0.041366502888357748
In [62]:
M
Out[62]:
array([[ 0.93875912,  0.43215004,  0.23129988],
       [ 0.13593153,  0.0413665 ,  0.21458492],
       [ 0.96261572,  0.22372779,  0.44478241]])
In [63]:
M[1]
Out[63]:
array([ 0.13593153,  0.0413665 ,  0.21458492])

Naravno, možemo koristiti i : operator:

In [64]:
M[1,:] # redak 1
Out[64]:
array([ 0.13593153,  0.0413665 ,  0.21458492])
In [65]:
M[:,1] # stupac 1
Out[65]:
array([ 0.43215004,  0.0413665 ,  0.22372779])
In [66]:
M[1,:] = 0
M[:,2] = -1
In [67]:
M
Out[67]:
array([[ 0.93875912,  0.43215004, -1.        ],
       [ 0.        ,  0.        , -1.        ],
       [ 0.96261572,  0.22372779, -1.        ]])
In [68]:
A = array([1,2,3,4,5])
A
Out[68]:
array([1, 2, 3, 4, 5])
In [69]:
A[1:3]
Out[69]:
array([2, 3])
In [70]:
A[1:3] = [-2,-3]
A
Out[70]:
array([ 1, -2, -3,  4,  5])
In [71]:
A[::]
Out[71]:
array([ 1, -2, -3,  4,  5])
In [72]:
A[::2]
Out[72]:
array([ 1, -3,  5])
In [73]:
A[:3]
Out[73]:
array([ 1, -2, -3])
In [74]:
A[3:]
Out[74]:
array([4, 5])

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]:
5
In [77]:
A[-3:] # zadnja tri elementa
Out[77]:
array([3, 4, 5])

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]:
array([[ 0,  1,  2,  3,  4],
       [10, 11, 12, 13, 14],
       [20, 21, 22, 23, 24],
       [30, 31, 32, 33, 34],
       [40, 41, 42, 43, 44]])
In [79]:
A[1:4, 1:4]
Out[79]:
array([[11, 12, 13],
       [21, 22, 23],
       [31, 32, 33]])
In [80]:
A[::2, ::2]
Out[80]:
array([[ 0,  2,  4],
       [20, 22, 24],
       [40, 42, 44]])
In [81]:
indeksi_redaka = [1, 2, 3]
A[indeksi_redaka]
Out[81]:
array([[10, 11, 12, 13, 14],
       [20, 21, 22, 23, 24],
       [30, 31, 32, 33, 34]])
In [82]:
indeksi_stupaca = [1, 2, -1]
A[indeksi_redaka, indeksi_stupaca]
Out[82]:
array([11, 22, 34])

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]:
array([0, 1, 2, 3, 4])
In [84]:
maska = array([True, False, True, False, False])
B[maska]
Out[84]:
array([0, 2])
In [85]:
maska = array([1,0,1,0,0], dtype=bool)
B[maska]
Out[85]:
array([0, 2])

Zanimljiviji primjer:

In [86]:
x = arange(0, 10, 0.5)
x
Out[86]:
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5,  5. ,
        5.5,  6. ,  6.5,  7. ,  7.5,  8. ,  8.5,  9. ,  9.5])
In [87]:
maska = (5 < x) * (x < 7.5)
maska
Out[87]:
array([False, False, False, False, False, False, False, False, False,
       False, False,  True,  True,  True,  True, False, False, False,
       False, False], dtype=bool)
In [88]:
x[maska]
Out[88]:
array([ 5.5,  6. ,  6.5,  7. ])

Funkcije na nizovima

In [89]:
indeksi = where(maska)
indeksi
Out[89]:
(array([11, 12, 13, 14]),)
In [90]:
x[indeksi]
Out[90]:
array([ 5.5,  6. ,  6.5,  7. ])
In [91]:
print(A)
diag(A)
[[ 0  1  2  3  4]
 [10 11 12 13 14]
 [20 21 22 23 24]
 [30 31 32 33 34]
 [40 41 42 43 44]]
Out[91]:
array([ 0, 11, 22, 33, 44])
In [92]:
diag(A, -1)
Out[92]:
array([10, 21, 32, 43])
In [93]:
v2 = arange(-3,3)
v2
Out[93]:
array([-3, -2, -1,  0,  1,  2])
In [94]:
indeksi_redaka = [1, 3, 5]
v2[indeksi_redaka]
Out[94]:
array([-2,  0,  2])
In [95]:
v2.take(indeksi_redaka)
Out[95]:
array([-2,  0,  2])

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]:
array([-2,  0,  2])

Funkcija choose:

In [97]:
koji = [1, 0, 1, 0]
izbori = [[-1,-2,-3,-4], [5,4,3,2]]

choose(koji, izbori)
Out[97]:
array([ 5, -2,  3, -4])

Što radi ova funkcija?

Vektorizacija koda

Što je više operacija s nizovima, to će kod generalno biti brži.

In [98]:
v1 = arange(0, 5)
In [99]:
v1 * 2
Out[99]:
array([0, 2, 4, 6, 8])
In [100]:
v1 + 2
Out[100]:
array([2, 3, 4, 5, 6])
In [101]:
print(A)
A * 2, A + 2
[[ 0  1  2  3  4]
 [10 11 12 13 14]
 [20 21 22 23 24]
 [30 31 32 33 34]
 [40 41 42 43 44]]
Out[101]:
(array([[ 0,  2,  4,  6,  8],
        [20, 22, 24, 26, 28],
        [40, 42, 44, 46, 48],
        [60, 62, 64, 66, 68],
        [80, 82, 84, 86, 88]]), array([[ 2,  3,  4,  5,  6],
        [12, 13, 14, 15, 16],
        [22, 23, 24, 25, 26],
        [32, 33, 34, 35, 36],
        [42, 43, 44, 45, 46]]))

Defaultne operacije na nizovima su uvijek definirane po elementima.

In [102]:
A * A
Out[102]:
array([[   0,    1,    4,    9,   16],
       [ 100,  121,  144,  169,  196],
       [ 400,  441,  484,  529,  576],
       [ 900,  961, 1024, 1089, 1156],
       [1600, 1681, 1764, 1849, 1936]])
In [103]:
v1 * v1
Out[103]:
array([ 0,  1,  4,  9, 16])
In [104]:
A.shape, v1.shape
Out[104]:
((5, 5), (5,))
In [122]:
print(A,v1)
A * v1
[[ 0  1  2  3  4]
 [10 11 12 13 14]
 [20 21 22 23 24]
 [30 31 32 33 34]
 [40 41 42 43 44]] [0 1 2 3 4]
Out[122]:
array([[  0,   1,   4,   9,  16],
       [  0,  11,  24,  39,  56],
       [  0,  21,  44,  69,  96],
       [  0,  31,  64,  99, 136],
       [  0,  41,  84, 129, 176]])

Kako doći do standardnog umnoška?

In [123]:
dot(A, A)
Out[123]:
array([[ 300,  310,  320,  330,  340],
       [1300, 1360, 1420, 1480, 1540],
       [2300, 2410, 2520, 2630, 2740],
       [3300, 3460, 3620, 3780, 3940],
       [4300, 4510, 4720, 4930, 5140]])
In [124]:
A @ A # nova operacija definirana u Python-u 3.5+
Out[124]:
array([[ 300,  310,  320,  330,  340],
       [1300, 1360, 1420, 1480, 1540],
       [2300, 2410, 2520, 2630, 2740],
       [3300, 3460, 3620, 3780, 3940],
       [4300, 4510, 4720, 4930, 5140]])
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]:
array([[ 300,  310,  320,  330,  340],
       [1300, 1360, 1420, 1480, 1540],
       [2300, 2410, 2520, 2630, 2740],
       [3300, 3460, 3620, 3780, 3940],
       [4300, 4510, 4720, 4930, 5140]])
In [126]:
dot(A, v1)
Out[126]:
array([ 30, 130, 230, 330, 430])
In [127]:
A @ v1
Out[127]:
array([ 30, 130, 230, 330, 430])
In [128]:
v1 @ v1 # analogno dot(v1, v1)
Out[128]:
30

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]:
(8, 13, 13)

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]:
matrix([[0],
        [1],
        [2],
        [3],
        [4]])
In [132]:
M*M
Out[132]:
matrix([[ 300,  310,  320,  330,  340],
        [1300, 1360, 1420, 1480, 1540],
        [2300, 2410, 2520, 2630, 2740],
        [3300, 3460, 3620, 3780, 3940],
        [4300, 4510, 4720, 4930, 5140]])
In [133]:
M*v
Out[133]:
matrix([[ 30],
        [130],
        [230],
        [330],
        [430]])
In [134]:
# skalarni produkt
v.T * v
Out[134]:
matrix([[30]])
In [135]:
v + M*v
Out[135]:
matrix([[ 30],
        [131],
        [232],
        [333],
        [434]])

Naravno, dimenzije trebaju biti kompatibilne.

In [136]:
v = matrix([1,2,3,4,5,6]).T
In [137]:
shape(M), shape(v)
Out[137]:
((5, 5), (6, 1))
In [138]:
M * v
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-138-995fb48ad0cc> in <module>()
----> 1 M * v

/projects/anaconda3/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py in __mul__(self, other)
    341         if isinstance(other, (N.ndarray, list, tuple)) :
    342             # This promotes 1-D vectors to row vectors
--> 343             return N.dot(self, asmatrix(other))
    344         if isscalar(other) or not hasattr(other, '__rmul__') :
    345             return N.dot(self, other)

ValueError: shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)

Još neke funkcije: inner, outer, cross, kron, tensordot.

In [139]:
C = matrix([[1j, 2j], [3j, 4j]])
C
Out[139]:
matrix([[ 0.+1.j,  0.+2.j],
        [ 0.+3.j,  0.+4.j]])
In [140]:
conjugate(C)
Out[140]:
matrix([[ 0.-1.j,  0.-2.j],
        [ 0.-3.j,  0.-4.j]])

Adjungiranje:

In [141]:
C.H
Out[141]:
matrix([[ 0.-1.j,  0.-3.j],
        [ 0.-2.j,  0.-4.j]])

Za izvlačenje realnog, odnosno imaginarnog dijela: real i imag:

In [142]:
real(C) # isto što i C.real
Out[142]:
matrix([[ 0.,  0.],
        [ 0.,  0.]])
In [143]:
imag(C) # isto što i C.imag
Out[143]:
matrix([[ 1.,  2.],
        [ 3.,  4.]])
In [144]:
angle(C+1) # u MATLAB-u je to funkcija arg, dakle argument (faza) kompleksnog broja
Out[144]:
array([[ 0.78539816,  1.10714872],
       [ 1.24904577,  1.32581766]])
In [145]:
abs(C)
Out[145]:
matrix([[ 1.,  2.],
        [ 3.,  4.]])
In [146]:
from numpy.linalg import inv, det
inv(C) # isto što i C.I 
Out[146]:
matrix([[ 0.+2.j ,  0.-1.j ],
        [ 0.-1.5j,  0.+0.5j]])
In [147]:
C.I * C
Out[147]:
matrix([[  1.00000000e+00+0.j,   0.00000000e+00+0.j],
        [  1.11022302e-16+0.j,   1.00000000e+00+0.j]])
In [148]:
det(C)
Out[148]:
(2.0000000000000004+0j)
In [149]:
det(C.I)
Out[149]:
(0.49999999999999967+0j)

Izvlačenje osnovih informacija iz nizova

In [150]:
# u stockholm_td_adj.dat su podaci o vremenu za Stockholm
dataStockholm = genfromtxt('stockholm_td_adj.dat')
dataStockholm.shape
Out[150]:
(77431, 7)
In [151]:
# temperatura se nalazi u 4. stupcu (znači stupcu broj 3)
mean(dataStockholm[:,3])
Out[151]:
6.1971096847515854

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]:
(8.2822716213405734, 68.596023209663414)
In [153]:
dataStockholm[:,3].min()
Out[153]:
-25.800000000000001
In [154]:
dataStockholm[:,3].max()
Out[154]:
28.300000000000001
In [155]:
d = arange(0, 10)
d
Out[155]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [156]:
sum(d)
Out[156]:
45
In [157]:
prod(d+1)
Out[157]:
3628800
In [158]:
# kumulativa suma
cumsum(d)
Out[158]:
array([ 0,  1,  3,  6, 10, 15, 21, 28, 36, 45])
In [159]:
# kumulativan produkt
cumprod(d+1)
Out[159]:
array([      1,       2,       6,      24,     120,     720,    5040,
         40320,  362880, 3628800])
In [160]:
# isto što i: diag(A).sum()
trace(A)
Out[160]:
110

Naravno, sve ove operacije možemo raditi na dijelovima nizova.

In [161]:
!head -n 3 stockholm_td_adj.dat
1800  1  1    -6.1    -6.1    -6.1 1
1800  1  2   -15.4   -15.4   -15.4 1
1800  1  3   -15.0   -15.0   -15.0 1

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]:
array([  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,
        12.])
In [163]:
maska_velj = dataStockholm[:,1] == 2
In [164]:
mean(dataStockholm[maska_velj,3])
Out[164]:
-3.2121095707365961

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.");

Rad s višedimenzionalnim podacima

In [166]:
m = rand(3,3)
m
Out[166]:
array([[ 0.66942337,  0.98488678,  0.06962048],
       [ 0.93170674,  0.70455373,  0.10112863],
       [ 0.4101218 ,  0.20957115,  0.9954116 ]])
In [167]:
m.max()
Out[167]:
0.99541159521774658
In [168]:
# max u svakom stupcu
m.max(axis=0)
Out[168]:
array([ 0.93170674,  0.98488678,  0.9954116 ])
In [169]:
# max u svakom retku
m.max(axis=1)
Out[169]:
array([ 0.98488678,  0.93170674,  0.9954116 ])

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]:
array([[ 0,  1,  2,  3,  4],
       [10, 11, 12, 13, 14],
       [20, 21, 22, 23, 24],
       [30, 31, 32, 33, 34],
       [40, 41, 42, 43, 44]])
In [171]:
n, m = A.shape
In [172]:
B = A.reshape((1,n*m))
B
Out[172]:
array([[ 0,  1,  2,  3,  4, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31,
        32, 33, 34, 40, 41, 42, 43, 44]])
In [173]:
B[0,0:5] = 5 # promijenili smo B
B
Out[173]:
array([[ 5,  5,  5,  5,  5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31,
        32, 33, 34, 40, 41, 42, 43, 44]])
In [174]:
A # a time smo promijenili i A
Out[174]:
array([[ 5,  5,  5,  5,  5],
       [10, 11, 12, 13, 14],
       [20, 21, 22, 23, 24],
       [30, 31, 32, 33, 34],
       [40, 41, 42, 43, 44]])

Funkcija flatten radi kopiju.

In [175]:
B = A.flatten()
B
Out[175]:
array([ 5,  5,  5,  5,  5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31,
       32, 33, 34, 40, 41, 42, 43, 44])
In [176]:
B[0:5] = 10
B
Out[176]:
array([10, 10, 10, 10, 10, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31,
       32, 33, 34, 40, 41, 42, 43, 44])
In [177]:
A # A je sad ostao isti
Out[177]:
array([[ 5,  5,  5,  5,  5],
       [10, 11, 12, 13, 14],
       [20, 21, 22, 23, 24],
       [30, 31, 32, 33, 34],
       [40, 41, 42, 43, 44]])
In [178]:
v = array([1,2,3])
In [179]:
shape(v)
Out[179]:
(3,)
In [180]:
# pretvorimo v u matricu
v[:, newaxis]
Out[180]:
array([[1],
       [2],
       [3]])
In [181]:
v[:,newaxis].shape
Out[181]:
(3, 1)
In [182]:
v[newaxis,:].shape
Out[182]:
(1, 3)
In [183]:
a = array([[1, 2], [3, 4]])
In [184]:
# ponovimo svaki element tri puta
repeat(a, 3)
Out[184]:
array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])
In [185]:
tile(a, 3)
Out[185]:
array([[1, 2, 1, 2, 1, 2],
       [3, 4, 3, 4, 3, 4]])
In [186]:
b = array([[5, 6]])
In [187]:
concatenate((a, b), axis=0)
Out[187]:
array([[1, 2],
       [3, 4],
       [5, 6]])
In [188]:
concatenate((a, b.T), axis=1)
Out[188]:
array([[1, 2, 5],
       [3, 4, 6]])
In [189]:
vstack((a,b))
Out[189]:
array([[1, 2],
       [3, 4],
       [5, 6]])
In [190]:
hstack((a,b.T))
Out[190]:
array([[1, 2, 5],
       [3, 4, 6]])

Kopiranje nizova

In [191]:
A = array([[1, 2], [3, 4]])
A
Out[191]:
array([[1, 2],
       [3, 4]])
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)
1
2
3
4
In [195]:
M = array([[1,2], [3,4]])

for row in M:
    print ("redak {}".format(row))
    
    for element in row:
        print (element)
redak [1 2]
1
2
redak [3 4]
3
4

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
indeks retka 0 redak [1 2]
col_idx 0 element 1
col_idx 1 element 2
indeks retka 1 redak [3 4]
col_idx 0 element 3
col_idx 1 element 4

Vektorizacija funkcija

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]))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-198-6658efdd2f22> in <module>()
----> 1 Theta(array([-3,-2,-1,0,1,2,3]))

<ipython-input-197-840f7d4ff406> in Theta(x)
      3     Sklarna verzija step funkcije.
      4     """
----> 5     if x >= 0:
      6         return 1
      7     else:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
In [199]:
Theta_vec = vectorize(Theta)
In [200]:
Theta_vec(array([-3,-2,-1,0,1,2,3]))
Out[200]:
array([0, 0, 0, 1, 1, 1, 1])

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]:
array([0, 0, 0, 1, 1, 1, 1])
In [203]:
# radi naravno i za skalare
Theta(-1.2), Theta(2.6)
Out[203]:
(0, 1)
In [204]:
M
Out[204]:
array([[ 1,  4],
       [ 9, 16]])
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")
barem jedan element iz M je veći 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")
barem jedan element je manji ili jednak od 5

Eksplicitno pretvaranje podataka. Uvijek stvara novi niz.

In [207]:
M.dtype
Out[207]:
dtype('int64')
In [208]:
M2 = M.astype(float)
M2
Out[208]:
array([[  1.,   4.],
       [  9.,  16.]])
In [209]:
M2.dtype
Out[209]:
dtype('float64')
In [210]:
M3 = M.astype(bool)
M3
Out[210]:
array([[ True,  True],
       [ True,  True]], dtype=bool)
In [211]:
from verzije import *
from IPython.display import HTML
HTML(print_sysinfo()+info_packages('numpy,matplotlib'))
Out[211]:
Python verzija3.5.3
kompajlerGCC 4.8.2 20140120 (Red Hat 4.8.2-15)
sustavLinux
broj CPU-a8
interpreter64bit
numpy verzija1.11.3
matplotlib verzija2.0.0

Zadaci za vježbu

  • Matrica $A$ reda 5 je dobijena s 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$.
  • Dan je kod
    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.
  • Vektorizirajte kod iz 3. zadatka za vježbu iz prvog predavanja. Vektorizirana funkcija treba za argumente primati funkciju 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.
  • Dana je funkcija $$ f(x)=\frac{n}{n+1}\begin{cases} (1/2)^{1+1/n}-(1/2-x)^{1+1/n}, & 0\le x\le 1/2,\\ (1/2)^{1+1/n}-(x-1/2)^{1+1/n}, & 1/2 < x\le 1. \end{cases} $$ Ovdje je $n$ realan broj, $0 < n \le 1$. Napišite vektoriziranu funkciju za računanje $f(x)$ na skupu $m$ ekvidistribuiranih brojeva između 0 i 1 (dakle, bez korištenja petlji).
  • Neka su $x_1,\ldots,x_n$ uniformno distribuirani slučajni brojevi između $a$ i $b$. Tada se $\int_a^b f(x)\mathrm{d}\,x$ može aproksimirati s $\frac{b-a}{n} \sum_{i=1}^n f(x_i)$, postupak koji se obično zove Monte Carlo integracija. Napišite funkciju koja kao ulazne varijable prima $a$, $b$, $f$ te $n$ s predefiniranom vrijednošću 1000, a vraća rezultat Monte Carlo integracije. I u ovom zadatku se ne smiju koristiti petlje.