numpy_essentials
  |   Source

Numpy Essentials

In [3]:
import numpy as np

Numpy Arrays

In [4]:
a = np.array([1, 2, 3, 5, 6, 7]) # a one dimensional array or singleton    
print type(a) 
<type 'numpy.ndarray'>
In [17]:
print a.shape        # technically 6x1, numpy would omit the one.
print a
(6,)
[5 2 3 5 6 7]
In [15]:
b = np.array([[1,2,3],[4,5,6]])  # a two dimensional array   
print b.shape  
print b
  
(2, 3)
[[1 2 3]
 [4 5 6]]
In [14]:
c = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[10,11,12],[13,14,15],[16,17,18]],[[19,20,21],[22,23,24],[26,27,28]]])
print c.shape
print c
(3, 3, 3)
[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[10 11 12]
  [13 14 15]
  [16 17 18]]

 [[19 20 21]
  [22 23 24]
  [26 27 28]]]

numpy index appetizers

In [18]:
print a[0], a[1], a[2], a[3]   
a[0] = 5                 
print a                  
5 2 3 5
[5 2 3 5 6 7]
In [19]:
print b[0, 0], b[0, 1], b[1, 0]
1 2 4
In [21]:
print c[0,0,0]
1

numpy datatypes

In [67]:
x = np.array([1, 2])  # numpy chooses the datatype
print x.dtype       
int64
In [65]:
x = np.array([1.0, 2.0])  # numpy choose the datatype
print x.dtype 
float64
In [66]:
x = np.array([1, 2], dtype=np.int64)  # Force a particular datatype
print x.dtype          
int64

special numpy functions for creating arrays

In [23]:
a = np.zeros((4,4))  # need a two dimensional 4x4 array full of zeros
print a
[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]
In [25]:
a = np.ones((4,4)) # what if I need ones
print a
[[ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]]
In [27]:
a = np.full((4,4), 6)  # If I want to fill my arrays with one number
print a
[[ 6.  6.  6.  6.]
 [ 6.  6.  6.  6.]
 [ 6.  6.  6.  6.]
 [ 6.  6.  6.  6.]]
In [29]:
a = np.eye(4)  # Identity matrix
print a
[[ 1.  0.  0.  0.]
 [ 0.  1.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 0.  0.  0.  1.]]
In [30]:
a = np.random.random((4,4))  # random numbers. we eventually deal with probability functions with scipy.stats
print a
[[ 0.67203674  0.17988745  0.99289883  0.42669069]
 [ 0.42571779  0.71770183  0.03735104  0.47549177]
 [ 0.91984388  0.2871378   0.4957902   0.67101606]
 [ 0.54119456  0.65936946  0.18833304  0.81093336]]
In [33]:
a = np.arange(10)
print a
[0 1 2 3 4 5 6 7 8 9]
In [35]:
a = np.magic(3) # my favourite from matlab.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-35-dc81c8a0c191> in <module>()
----> 1 a = np.magic(3) # my favourite from matlab.

AttributeError: 'module' object has no attribute 'magic'

oops! sorry not in numpy. So let's try to make ours.

for what?????

1. If you want to have an idea of the magic called numpy.

2. Magic squares are kind of cool. sum all the rows in a column and all the columns in a row, you get the same result.

Algorithm

Step 1. Start in the middle of the top row, and let n=1;

Step 2. Insert n into the current grid position;

Step 3. If n=NxN the grid is complete so stop. Otherwise increment n;

Step 4. Move diagonally up and right, wrapping to the first column or last row if the move leads outside the grid. If this cell is already filled, move vertically down one space instead;

Step 5. Return to step 2.

In [34]:
# NxN magic square.  Extra credit stuff
import numpy as np

N  = 3
magic_square = np.zeros((N,N), dtype=int)

n = 1
i, j = 0, N//2  # check below if the // is weird

while n <= N**2:  # while n is less than NxN
    magic_square[i, j] = n
    n += 1
    newi, newj = (i-1) % N, (j+1)% N # some modular arithmetic so that we never go out of bounds
    if magic_square[newi, newj]:
        i += 1
    else:
        i, j = newi, newj

print(magic_square)


# In Python 3.0, 5 / 2 will return 2.5 and 5 // 2 will return 2. 
# The former is floating point division, and the latter is floor division, sometimes also called integer division.
# In Python 2.2 or later in the 2.x line, there is no difference
# reference http://stackoverflow.com/questions/183853/in-python-2-what-is-the-difference-between-and-when-used-for-division
[[8 1 6]
 [3 5 7]
 [4 9 2]]

Numpy Array Indexing

In [45]:
print b
[[1 2 3]
 [4 5 6]]
In [44]:
print b[:1,:2]  # slice indexing
[[1 2]]
In [46]:
print "sliced b:{}".format(b[:1,:2])  # if you want to print like a pro
sliced b:[[1 2]]
In [49]:
# use slicing to get all the second rows
print b[1,:]
[4 5 6]
In [50]:
# or all the secondcolumn
print b[:,1]
[2 5]
In [54]:
# or get second and third rows
print b[:,1:]
[[2 3]
 [5 6]]
In [55]:
# be careful with the indexing, it starts from the first number and ends in (second nuber -1)
In [56]:
print b
[[1 2 3]
 [4 5 6]]
In [58]:
print np.array([b[0,0],b[1,0], b[1,2]]) # same as below  # integer indexing
[1 4 6]
In [59]:
print b[[0,1,1],[0,0,2]]  # same as above  # integer indexing
[1 4 6]
In [61]:
# you can perform operations on this subset of the whole array.
b[[0,1,1],[0,0,2]] += 10
print b
[[11  2  3]
 [14  5 16]]
In [62]:
print b > 10  # boolean indexing
[[ True False False]
 [ True False  True]]
In [63]:
print b[b>10]
[11 14 16]

Numpy array Math operations

In [72]:
x = np.array([[1,2,3],[4,5,6]])
y = np.array([[2,2,2],[3,3,3]])
In [73]:
print x+y
print np.add(x,y)
[[3 4 5]
 [7 8 9]]
[[3 4 5]
 [7 8 9]]
In [74]:
print x-y
print np.add(x,y)
[[-1  0  1]
 [ 1  2  3]]
[[3 4 5]
 [7 8 9]]
In [76]:
print x*y
print np.multiply(x,y)
[[ 2  4  6]
 [12 15 18]]
[[ 2  4  6]
 [12 15 18]]
In [79]:
print x/y
print np.divide(x,y)
[[0 1 1]
 [1 1 2]]
[[0 1 1]
 [1 1 2]]
In [80]:
print np.sqrt(x)
[[ 1.          1.41421356  1.73205081]
 [ 2.          2.23606798  2.44948974]]
In [83]:
v = np.array([2,1,2])
In [84]:
print x.shape
print v.shape
(2, 3)
(3,)
In [85]:
# matrix multiplication is possible for x and v  or  for y and v.  # note the order
print x.dot(v)
[10 25]
In [86]:
print np.dot(x,v)
[10 25]
In [89]:
# what if we try to change the order, disobeying matrix multiplication rule.
print np.dot(v,x)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-89-530e926960fc> in <module>()
      1 # what if we try to change the order, disobeying matrix multiplication rule.
----> 2 print np.dot(v,x)

ValueError: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)

oops ! numpy doesn't allow that.

In [91]:
print x
print np.sum(x) # sums all the elements of x
[[1 2 3]
 [4 5 6]]
21
In [92]:
print np.sum(x, axis=0) # sums all the the columns.
[5 7 9]
In [93]:
print np.sum(x, axis=1) # sums all the rows.
[ 6 15]
In [94]:
print x.T
[[1 4]
 [2 5]
 [3 6]]
In [96]:
print x.flatten()
[1 2 3 4 5 6]

Array Broadcasting

useful for performing a repeated operation on a large numpy array by a small one.

Consider a scenario where we would like to subtract a small array from all the rows of a bigger one.

In [99]:
# first approach 
x = np.array([[1,2,3], [4,5,6], [7,8,9]])
v = np.array([1, 1, 1])
y = np.empty_like(x)   # Create an empty matrix with the same shape as x

# subtract vector v from each row of matrix x with a for loop
for i in range(x.shape[1]):
    y[i, :] = x[i, :] - v
    
print y    

# with a very large x, the loop could be very slow
[[0 1 2]
 [3 4 5]
 [6 7 8]]
In [101]:
# second approach
# we would pile the v's on top each other
vv = np.tile(v, (3, 1))
y = x - vv
print y
[[0 1 2]
 [3 4 5]
 [6 7 8]]
In [102]:
# third approach. numpy broadcasting allows us to do this without piling arrays
y = x-v
print y
[[0 1 2]
 [3 4 5]
 [6 7 8]]

END For Now

Comments powered by Disqus