# Python - NumPy

NumPy is a Python library for working with arrays.

NumPy provides abstractions that make it easy to treat these underlying arrays as vectors and matrices.

## 3 - Initialization

### 3.2 - Import

```# It is convention to import NumPy with the alias np
import numpy as np```

## 4 - Vector Operations

### 4.1 - Vector construction

The building block for NumPy is the ndarray, which is a multidimensional array of fixed-size that contains elements of one type (e.g. array of floats).

A numpy array with the values 1, 2, 3

```simpleArray = np.array([1, 2, 3])
print simpleArray
[1 2 3]```

### 4.2 - Combine

#### 4.2.1 - Horizontal

```>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.hstack((a,b))
array([1, 2, 3, 2, 3, 4])
>>> a = np.array([[1],[2],[3]])
>>> b = np.array([[2],[3],[4]])
>>> np.hstack((a,b))
array([[1, 2],
[2, 3],
[3, 4]])```

#### 4.2.2 - Vertical

```>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.vstack((a,b))
array([[1, 2, 3],
[2, 3, 4]])```

### 4.3 - Scalar Product

```timesFive = 5*simpleArray
[ 5 10 15]```

### 4.4 - Element-wise multiplication

Element-wise multiplication occurs automatically when you use the * operator to multiply two ndarray objects of the same length.

```u = np.arange(0, 5, .5)
v = np.arange(5, 10, .5)

elementWise = u*v
print 'u: {0}'.format(u)
print 'v: {0}'.format(v)
print '\nelementWise\n{0}'.format(elementWise)

u: [ 0.   0.5  1.   1.5  2.   2.5  3.   3.5  4.   4.5]
v: [ 5.   5.5  6.   6.5  7.   7.5  8.   8.5  9.   9.5]

elementWise
[  0.     2.75   6.     9.75  14.    18.75  24.    29.75  36.    42.75]```

### 4.5 - Dot product

To perform the dot product you can use either np.dot() or np.ndarray.dot().

For example, if you had NumPy arrays x and y, you could compute their dot product four ways:

```np.dot(x, y)
np.dot(y, x)
x.dot(y)
y.dot(x)```

Example:

```u = np.arange(0, 5, .5)
v = np.arange(5, 10, .5)

dotProduct = u.dot(v)
print 'u: {0}'.format(u)
print 'v: {0}'.format(v)

u: [ 0.   0.5  1.   1.5  2.   2.5  3.   3.5  4.   4.5]
v: [ 5.   5.5  6.   6.5  7.   7.5  8.   8.5  9.   9.5]

dotProduct
183.75```

## 5 - Matrix Operations

You can perform matrix math on NumPy matrices using *.

### 5.1 - Matrix Construction

You can use np.matrix() to generate a NumPy matrix. Just pass a two-dimensional ndarray or a list of lists to the function. You can perform matrix math on NumPy matrices using *.

```A = np.matrix([[1,2,3,4],[5,6,7,8]])
print 'A:\n{0}'.format(A)

A:
[[1 2 3 4]
[5 6 7 8]]```

### 5.2 - Transpose

You can transpose a matrix :

```# Print A transpose
print '\nA transpose:\n{0}'.format(A.T)

A transpose:
[[1 5]
[2 6]
[3 7]
[4 8]]```

### 5.3 - Inverting

Inverting a matrix can be done using numpy.linalg.inv().

```# Multiply A by A transpose
AAt = A * A.T
print '\nAAt:\n{0}'.format(AAt)

AAt:
[[ 30  70]
[ 70 174]]

# Invert AAt with np.linalg.inv()
from numpy.linalg import inv
AAtInv = np.linalg.inv(A * A.T)
print '\nAAtInv:\n{0}'.format(AAtInv)

AAtInv:
[[ 0.54375 -0.21875]
[-0.21875  0.09375]]

# Show inverse times matrix equals identity
# We round due to numerical precision
print '\nAAtInv * AAt:\n{0}'.format((AAtInv * AAt).round(4))

AAtInv * AAt:
[[ 1.  0.]
[-0.  1.]]```