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.

In [ ]: