#!/usr/bin/env python
# coding: utf-8
# # Numpy Basic Concepts
# In[1]:
import addutils.toc ; addutils.toc.js(ipy_notebook=True)
# In[2]:
from addutils import css_notebook
css_notebook()
# ## 1 What is Numpy ?
# NumPy is the fundamental package for scientific computing with Python. It is:
#
# * a powerful Python extension for N-dimensional array
# * a tool for integrating C/C++ and Fortran code
# * designed for scientific computation: linear algebra and Signal Analysis
#
# If you are a MATLAB® user we recommend to read [Numpy for MATLAB Users](http://www.scipy.org/NumPy_for_Matlab_Users) and [Benefit of Open Source Python versus commercial packages](http://www.scipy.org/NumPyProConPage). For an idea of the Open Source Approach to science, we suggest the [Science Code Manifesto](http://sciencecodemanifesto.org/)
# ### 1.1 Documentation and reference:
# * [Numpy Reference guide](http://docs.scipy.org/doc/numpy/reference/)
# * [SciPy Reference](http://docs.scipy.org/doc/scipy/reference/)
# * [Scipy Topical Software](http://www.scipy.org/Topical_Software)
# * [Numpy Functions by Category](http://www.scipy.org/Numpy_Functions_by_Category)
# * [Numpy Example List With Doc](http://www.scipy.org/Numpy_Example_List_With_Doc)
# Lets start by checking the Numpy version used in this Notebook:
# In[3]:
import numpy as np
print ('numpy version: ', np.__version__)
# ## 2 Array Creation
# NumPy's main object is the homogeneous ***multidimensional array***. It is a table of elements (usually numbers), all of the same type. In Numpy dimensions are called ***axes***. The number of axes is called ***rank***. The most important attributes of an ndarray object are:
#
# * **ndarray.ndim** - the number of axes (dimensions) of the array.
# * **ndarray.shape** - the dimensions of the array. For a matrix with n rows and m columns, shape will be (n,m).
# * **ndarray.size** - the total number of elements of the array.
# * **ndarray.dtype** - numpy.int32, numpy.int16, and numpy.float64 are some examples.
# * **ndarray.itemsize** - the size in bytes of elements of the array. For example, elements of type float64 has itemsize 8 (=64/8)
# In[4]:
a = np.array([[0,1,2,3], [4,5,6,7], [8,9,10,11]])
rows, cols = np.shape(a)
print ('Rows:{0:03d} ; Cols:{0:03d}'.format(rows, cols))
# **Try by yourself** the following commands *(type or paste the commands in the cell below)*:
#
# a.ndim # Number of dimensions
# print a.dtype.name # Type of data
# a.itemsize # Size in bytes of elements
# a.size # Number of elements in the array
# In[5]:
a.ndim
# The type of the array can be specified at creation time:
# In[6]:
b = np.array([[2,3], [6,7]], dtype=np.complex64)
print (b)
# ### 2.1 Array creation functions
# Often, the elements of an array are originally unknown, but its size is known. Hence, **NumPy** offers several functions to create arrays with initial placeholder content.
#
# The function `zeros` creates an array full of zeros, the function `ones` creates an array full of ones, and the function `empty` creates an array whose initial content is random and depends on the state of the memory. By default, the dtype of the created array is float64.
# ***Try by yourself*** the following commands:
#
# zeros((3,4))
# ones((3,4))
# empty((2,3))
# eye(3)
# diag(np.arange(5))
# np.tile(np.array([[6, 7], [8, 9]]), (2, 2))
# In[7]:
np.zeros((3,4))
# `zeros_like, ones_like` and `empty_like` can be used to create arrays of the same type of a given one
# In[8]:
np.zeros_like(b)
# ### 2.2 Sequences and reshaping
# Arrays can be created with ***linspace***, ***logspace*** (returning evenly spaced numbers, linear or logarithmic) or ***arange*** and then shaped in matrix form. **mgrid** is like the equivaled "meshgrid" in MATLAB.
# In[9]:
np.logspace(1,5,3)
# In[10]:
x = np.arange(4).reshape(2,2)
# In[11]:
# Use List comprehention to create a matrix
c = np.array([[10*j+i for i in range(3)] for j in range(4)])
print (c)
# Use *'newaxis'* to add a dimension (as for turning a row vector in a column vector):
# In[12]:
d = np.linspace(0, 12, 5)
print (d)
print (d[:, np.newaxis]) # make into a column vector
# In[13]:
X, Y = np.mgrid[0:5, 0:5] # similar to meshgrid in MATLAB
X
# In[14]:
Y
# ### 2.3 Sparse Matrices
# We can create and manipulate sparse matrices as follows:
# In[15]:
from scipy import sparse
X = np.random.random((5, 6)) # Create an array with many zeros
X[X < 0.85] = 0
print (X)
X_csr = sparse.csr_matrix(X) # turn X into a csr (Compressed-Sparse-Row) matrix
print (X_csr)
# In[16]:
print (X_csr.toarray()) # convert back to a dense array
# There are several other sparse formats that can be useful for various problems:
#
# - `CSC` (compressed sparse column)
# - `BSR` (block sparse row)
# - `COO` (coordinate)
# - `DIA` (diagonal)
# - `DOK` (dictionary of keys)
#
# The ``scipy.sparse`` submodule also has a lot of functions for sparse matrices
# including linear algebra, sparse solvers, graph algorithms, and much more.
# ### 2.4 Random Numbers
# In[17]:
np.random.rand(4,5) # uniform random numbers in [0,1]
# In[18]:
np.random.randn(4,5) # standard normal distributed random numbers
# ### 2.5 Casting
# Forced casts:
# In[19]:
a = np.array([1.7, 1.2, 1.6])
b = a.astype(int) # <-- truncates to integer
b
# Rounding:
# In[20]:
a = np.array([1.2, 1.5, 1.6, 2.5, 3.5, 4.5])
b = np.around(a)
print (b) # still floating-point
c = np.around(a).astype(int)
print (c)
# ## 3 Basic Visualization with Bokeh
# In[21]:
import bokeh.plotting as bk
bk.output_notebook()
# ### 3.1 D Plotting
# In[22]:
x = np.linspace(0, 3, 20)
y = np.linspace(0, 9, 20)
fig = bk.figure()
fig.line(x, y)
fig.circle(x, y, color='green')
bk.show(fig)
# Somethimes, if the code is not relevant for the topic we are developing, we can put the code in a separate file and run it from the Notebook:
# In[23]:
from utilities import plot_01
bk.show(plot_01())
# At any time if you want to see the code, you can load it and run it directly from the cell in the Notebook:
# In[24]:
# %load utilities/plot_utilities.py
import numpy as np
import bokeh.plotting as bk
bk.output_notebook()
def plot_01():
image = np.random.randn(120, 120)
fig = bk.figure()
fig.image([image], x=[0], y=[0], dw=[1], dh=[1], palette='OrRd9')
return fig
if __name__ == '__main__':
fig = plot_01()
bk.show(fig)
# ## 4 Basic Linear Algebra
# In[25]:
# Transpose
print (x.T)
# Explore the available commands for numpy arrays (press x.+TAB) ***Try by yourself:***
#
# x.min()
# x.max()
# x.mean()
# x.cumsum()
# In[26]:
x.min()
# In[27]:
print (x*5) # Scalar expansion
print (x+3)
# In[28]:
print (x*x.T) # Elementwise product
print (np.dot(x,x.T)) # Dot (matrix) product
# ### 4.1 Determinant of a square matrix
# The `scipy.linalg.det()` function computes the determinant of a square matrix:
# In[29]:
from scipy import linalg
arr = np.array([[1, 2],
[3, 4]])
linalg.det(arr)
# ### 4.2 Inverse of a square matrix
# The `scipy.linalg.inv()` function computes the inverse of a square matrix:
# In[30]:
print (linalg.inv(arr))
# ### 4.3 Advanced Linear Algebra
# In **Scipy** many advanced operations are available (check the Scipy Reference), for example singular-value decomposition (SVD):
# In[31]:
arr = np.arange(9).reshape((3, 3)) + np.diag([1, 0, 1])
uarr, spec, vharr = linalg.svd(arr)
# The resulting array spectrum is:
# In[32]:
spec
# ## 5 Slicing -Indexing for MATLAB® Users-
# For MATLAB® users: in Python, like many other languages, indexing start from **zero** and not from one like MATLAB.
#
# Remember: slices (indexed subarrays) are references to memory in the original array, this means that if you modify a slice, you modify the original array. In other words a slice is a pointer to the original array.
# In[33]:
b = np.arange(8).reshape(2,4)
print (b)
# ### 5.1 Indexing single elements
# ***Try by yourself:***
#
# print b[0,0]
# print b[-1,-1] # Last element
# print b[:,1] # column number 1 (second column)
# In[34]:
# Indexing single elements
# *Figure 01*
# ### 5.2 Indexing by rows and columns
# In[35]:
# With reference to Figure 01:
a = np.array([[10*j+i for i in range(6)] for j in range(6)])
# ***Try by yourself:***
#
# print a[0,3:5] # Orange
# print a[4:,4:] # Blue
# print a[:, 2] # Red
# print a[2::2, ::2] # Green
# In[36]:
#Indexing multiple elements
# To replicate an array use 'copy':
# In[37]:
c = np.array(a, copy=True)
# ## 6 File Input / Output
# Numpy has special functions for:
#
# * Load/Save text files: `numpy.loadtxt()`/`numpy.savetxt()`
# * Clever loading of text/csv files: `numpy.genfromtxt()`/`numpy.recfromcsv()`
# * Fast and efficient, but numpy-specific, binary format: `numpy.save()`/`numpy.load()`
#
# In particular Numpy can load and save native MATLAB® files:
# In[38]:
from scipy import io as spio
spio.savemat('temp/test.mat', {'c': c}, oned_as='row') # savemat expects a dictionary
data = spio.loadmat('temp/test.mat')
data['c']
# ---
#
# Visit [www.add-for.com]() for more tutorials and updates.
#
# This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.