In [123]:
import numpy as np

# an array is not like a list; all items are the same type
# arrays can be constructed from lists:

np.array([1,2,3,4,5])


Out[123]:
array([1, 2, 3, 4, 5])

In [124]:
# in any number of dimentions
np.array([[1,2,3],[4,5,6]])


Out[124]:
array([[1, 2, 3],
       [4, 5, 6]])

In [125]:
# generate a 5x2 matrix of random integers between 0 and 10
r = np.random.randint(10,size=(5,2))
r


Out[125]:
array([[7, 6],
       [6, 9],
       [8, 3],
       [4, 3],
       [2, 8]])

In [126]:
# get the 2nd column (column #1)
r[:,1]


Out[126]:
array([6, 9, 3, 3, 8])

In [127]:
# get the 4th row (row #3)
r[3,:]


Out[127]:
array([4, 3])

In [128]:
# get the first two rows
r[:2,:]


Out[128]:
array([[7, 6],
       [6, 9]])

In [129]:
# get the last row
r[-1,:]


Out[129]:
array([2, 8])

In [130]:
# get the last 3 rows
r[-3:,:]


Out[130]:
array([[8, 3],
       [4, 3],
       [2, 8]])

In [131]:
# get every other row
r[::2,:]


Out[131]:
array([[7, 6],
       [8, 3],
       [2, 8]])

In [132]:
# transpose the axes to make a 2x5 array
r.T


Out[132]:
array([[7, 6, 8, 4, 2],
       [6, 9, 3, 3, 8]])

In [133]:
# use multiple assignments to get the first and second columns
# from the transposed array
x, y = r.T
y


Out[133]:
array([6, 9, 3, 3, 8])

In [134]:
# IMPORTANT: reshaping arrays does not copy any data;
# it just changes the way the data is indexed. this is FAST.

#
r = np.array(range(10)).reshape((5,2))
r


Out[134]:
array([[0, 1],
       [2, 3],
       [4, 5],
       [6, 7],
       [8, 9]])

In [135]:
# now set rt to the transposed array
rt = r.T
rt


Out[135]:
array([[0, 2, 4, 6, 8],
       [1, 3, 5, 7, 9]])

In [136]:
# now multiply element 1,3 of the transposed array by 10
rt[1,3] *= 10
rt


Out[136]:
array([[ 0,  2,  4,  6,  8],
       [ 1,  3,  5, 70,  9]])

In [137]:
# r has also changed. they are interfaces to the same data
r


Out[137]:
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6, 70],
       [ 8,  9]])

In [138]:
# flattening or "raveling" arrays
# returns elements in order of axes
r.ravel()


Out[138]:
array([ 0,  1,  2,  3,  4,  5,  6, 70,  8,  9])

In [139]:
# reshape the flattened array to recover the original shape
r.ravel().reshape((5,2))


Out[139]:
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6, 70],
       [ 8,  9]])

In [140]:
# leave one dimension unspecified and it uses the appropriate
# shape
r.ravel().reshape((-1,2))


Out[140]:
array([[ 0,  1],
       [ 2,  3],
       [ 4,  5],
       [ 6, 70],
       [ 8,  9]])

In [141]:
# note that this does not produce r.T because
# the raveled array is in order of axes
r.ravel().reshape((2,-1))


Out[141]:
array([[ 0,  1,  2,  3,  4],
       [ 5,  6, 70,  8,  9]])

In [142]:
# to turn a row vector into a column vector, use reshape
np.array([1,2,3,4,5]).reshape(-1,1)


Out[142]:
array([[1],
       [2],
       [3],
       [4],
       [5]])

In [143]:
# everything works in any number of dimensions
d3 = np.array(range(27)).reshape((3,3,3))
d3


Out[143]:
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23],
        [24, 25, 26]]])

In [144]:
d3[1,0,2]


Out[144]:
11

In [145]:
d3[2,1:,:2]


Out[145]:
array([[21, 22],
       [24, 25]])

In [146]:
c = d3.reshape((3,-1))
c


Out[146]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23, 24, 25, 26]])

In [147]:
c[:,2]


Out[147]:
array([ 2, 11, 20])

In [148]:
row = np.array(range(9)) + 27
row


Out[148]:
array([27, 28, 29, 30, 31, 32, 33, 34, 35])

In [149]:
c2 = np.vstack((c,row))
c2


Out[149]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23, 24, 25, 26],
       [27, 28, 29, 30, 31, 32, 33, 34, 35]])

In [150]:
c3 = c2.reshape((6,6))
c3


Out[150]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

In [151]:
col = np.ones((6,1),dtype=int)
col


Out[151]:
array([[1],
       [1],
       [1],
       [1],
       [1],
       [1]])

In [152]:
c4 = np.hstack((c3,col))
c4


Out[152]:
array([[ 0,  1,  2,  3,  4,  5,  1],
       [ 6,  7,  8,  9, 10, 11,  1],
       [12, 13, 14, 15, 16, 17,  1],
       [18, 19, 20, 21, 22, 23,  1],
       [24, 25, 26, 27, 28, 29,  1],
       [30, 31, 32, 33, 34, 35,  1]])

In [153]:
# numerical operations are convenient
I = np.array(range(24)).reshape(4,6)
I


Out[153]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

In [154]:
# operation with a scalar performs operation elementwise
0 - I


Out[154]:
array([[  0,  -1,  -2,  -3,  -4,  -5],
       [ -6,  -7,  -8,  -9, -10, -11],
       [-12, -13, -14, -15, -16, -17],
       [-18, -19, -20, -21, -22, -23]])

In [155]:
# any necessary type conversions are done
I * 2.5


Out[155]:
array([[  0. ,   2.5,   5. ,   7.5,  10. ,  12.5],
       [ 15. ,  17.5,  20. ,  22.5,  25. ,  27.5],
       [ 30. ,  32.5,  35. ,  37.5,  40. ,  42.5],
       [ 45. ,  47.5,  50. ,  52.5,  55. ,  57.5]])

In [156]:
# logical operations work too
I > 8


Out[156]:
array([[False, False, False, False, False, False],
       [False, False, False,  True,  True,  True],
       [ True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True,  True]], dtype=bool)

In [157]:
# arithmetic operations can combine arrays in useful ways

# operation on a 2d array by a row vector performs operation per-row
# this avoids the MATLAB idiom of using "repmat" to tile copies of an array

I + np.array([0, 100, 0, 200, 0, 300])


Out[157]:
array([[  0, 101,   2, 203,   4, 305],
       [  6, 107,   8, 209,  10, 311],
       [ 12, 113,  14, 215,  16, 317],
       [ 18, 119,  20, 221,  22, 323]])

In [158]:
# operation on a 2d array by a column vector performs operation per-column
I * np.array([[0],
              [1],
              [1],
              [0]])


Out[158]:
array([[ 0,  0,  0,  0,  0,  0],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [ 0,  0,  0,  0,  0,  0]])

In [159]:
# operation on same-size array performs operation elementwise 
s = np.random.choice([0,2],size=(4,6))
s


Out[159]:
array([[2, 0, 0, 0, 2, 2],
       [0, 2, 0, 0, 0, 0],
       [2, 0, 0, 2, 0, 0],
       [0, 0, 2, 2, 0, 0]])

In [160]:
I * s


Out[160]:
array([[ 0,  0,  0,  0,  8, 10],
       [ 0, 14,  0,  0,  0,  0],
       [24,  0,  0, 30,  0,  0],
       [ 0,  0, 40, 42,  0,  0]])

In [161]:
# arithmetic operation using boolean converts boolean to 1,0
div5 = I % 5 == 0
div5


Out[161]:
array([[ True, False, False, False, False,  True],
       [False, False, False, False,  True, False],
       [False, False, False,  True, False, False],
       [False, False,  True, False, False, False]], dtype=bool)

In [162]:
I * div5


Out[162]:
array([[ 0,  0,  0,  0,  0,  5],
       [ 0,  0,  0,  0, 10,  0],
       [ 0,  0,  0, 15,  0,  0],
       [ 0,  0, 20,  0,  0,  0]])

In [163]:
# arrays can be used to index other arrays

pi = np.array([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2])
pi[[11,0,2,1]]


Out[163]:
array([8, 3, 4, 1])

In [164]:
# numpy.where can produce an index for a given condition

np.where(pi % 2 == 0)


Out[164]:
(array([ 2,  6,  7, 11, 16]),)

In [165]:
# indexing by boolean works too

pi[pi % 2 == 0]


Out[165]:
array([4, 2, 6, 8, 2])

In [166]:
# indexing by boolean can be used for assignment
J = np.random.randint(-2,3,size=(5,5))
J


Out[166]:
array([[ 1,  1,  2,  0,  1],
       [ 2, -2,  0,  2,  0],
       [ 2,  1,  2, -1, -1],
       [ 1, -2, -1,  2,  1],
       [-2,  0,  2,  0,  2]])

In [167]:
J[J < 0] = 99
J


Out[167]:
array([[ 1,  1,  2,  0,  1],
       [ 2, 99,  0,  2,  0],
       [ 2,  1,  2, 99, 99],
       [ 1, 99, 99,  2,  1],
       [99,  0,  2,  0,  2]])

In [168]:
# by the way, if you want to tile an array as with MATLAB's repmat, you can

t = np.array([1,2,3])
np.tile(t,(3,2))


Out[168]:
array([[1, 2, 3, 1, 2, 3],
       [1, 2, 3, 1, 2, 3],
       [1, 2, 3, 1, 2, 3]])

In [169]:
# create a non-inclusive range with arange

np.arange(5)


Out[169]:
array([0, 1, 2, 3, 4])

In [170]:
# give arange the inclusive minimum, exclusive maximum, and step

np.arange(1,3,0.2)


Out[170]:
array([ 1. ,  1.2,  1.4,  1.6,  1.8,  2. ,  2.2,  2.4,  2.6,  2.8])

In [171]:
# to create an inclusive range use linspace
# give it the inclusive minimum, inclusive maximum, and number of points
np.linspace(-1,1,4)


Out[171]:
array([-1.        , -0.33333333,  0.33333333,  1.        ])