numpy: Numerical Python

"Duck'' typing makes Python slow

  • Duck Typing

    • If it looks like a duck, then it is a duck.
    • a.k.a. dynamic typing
    • Dynamic typing requires lots of metadata around a variable.
  • Solution: numpy data structures
    • Data structures, as objects, that have a single type and continuous storage.
    • Common functionality with implementation in C.

How slow is Python?

  • Add 1 to a million numbers
    • Use timeit
In [1]:
%timeit [i+1 for i in range(1000000)]    
110 ms ± 13.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [2]:
import numpy
%timeit numpy.arange(1000000) + 1
1.22 ms ± 121 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Universal functions

  • Universal functions are vectorized functions that operate on arrays in an element-by-element fashion.
  • Arithmetic operators (+, -, /, *, **) are overloaded to work in an element-by-element fashion.

Another speed comparison:

In [3]:
import math
%timeit [math.sin(i) ** 2 for i in range(1000000)]
322 ms ± 40.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [4]:
import numpy
%timeit numpy.sin(numpy.arange(1000000)) ** 2
25.3 ms ± 2.51 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Creating numpy arrays

numpy offers several built-in functions for creating arrays

import numpy
x = numpy.array([2,3,11])
x = numpy.array([[1,2.],[0,0],[1+1j,2.]])
x = numpy.arange(-10,10,2, dtype=float)
x = numpy.linspace(1.,4.,6)
x = numpy.indices((3,3))
x = numpy.fromfile('foo.dat')

Array functions

numpy array functions for slicing, getting info, etc.

In [5]:
import numpy as np
x = np.arange(9).reshape(3,3)
x
Out[5]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
In [6]:
x[:,0]
Out[6]:
array([0, 3, 6])
In [7]:
x.shape
Out[7]:
(3, 3)
In [8]:
y = x[::2, ::2]
y
Out[8]:
array([[0, 2],
       [6, 8]])
In [9]:
y[0,0] = 100
y[0,0]
Out[9]:
100

Efficient and compact finite differences

In [10]:
x = np.arange(0,20,2)
y = x ** 2

dy_dx = (y[1:] - y[:-1]) / (x[1:] - x[:-1])
dy_dx
Out[10]:
array([  2.,   6.,  10.,  14.,  18.,  22.,  26.,  30.,  34.])

Sophisticated broadcasting rules

In [11]:
red = np.random.rand(800,600)
blue = np.random.rand(800, 600)
green = np.random.rand(800, 600)
rgb = np.array([red, blue, green])
rgb.shape
Out[11]:
(3, 800, 600)
In [12]:
rgb.T * np.array([0.5, 0.5, 0.5])
Out[12]:
array([[[ 0.0572915 ,  0.32313562,  0.16103862],
        [ 0.17728031,  0.13808923,  0.10237519],
        [ 0.31018678,  0.35407676,  0.32346525],
        ..., 
        [ 0.39877338,  0.44515327,  0.41391662],
        [ 0.0947496 ,  0.45246471,  0.38517163],
        [ 0.21095469,  0.36167983,  0.43376607]],

       [[ 0.32578771,  0.20908545,  0.27450444],
        [ 0.06499066,  0.29061026,  0.25727398],
        [ 0.4903594 ,  0.41556017,  0.12463315],
        ..., 
        [ 0.30675776,  0.3224342 ,  0.11740479],
        [ 0.04301273,  0.09905372,  0.44172653],
        [ 0.03688823,  0.27918651,  0.23945417]],

       [[ 0.14924607,  0.3934185 ,  0.1787775 ],
        [ 0.37542107,  0.02616865,  0.19181638],
        [ 0.0036889 ,  0.08759746,  0.28269157],
        ..., 
        [ 0.15305688,  0.07356994,  0.48027121],
        [ 0.31778989,  0.09474409,  0.03948814],
        [ 0.04076674,  0.1230122 ,  0.34899233]],

       ..., 
       [[ 0.28770621,  0.04297194,  0.0797577 ],
        [ 0.09302244,  0.00407896,  0.19471398],
        [ 0.49317651,  0.01786695,  0.34037306],
        ..., 
        [ 0.33641787,  0.00141393,  0.3542402 ],
        [ 0.07212021,  0.47950944,  0.11248765],
        [ 0.29026511,  0.0188487 ,  0.37162958]],

       [[ 0.26561951,  0.4719433 ,  0.0235921 ],
        [ 0.40664526,  0.0077357 ,  0.33035248],
        [ 0.19008087,  0.21865365,  0.28132663],
        ..., 
        [ 0.1313237 ,  0.49808581,  0.4155362 ],
        [ 0.01350529,  0.35242497,  0.14651145],
        [ 0.42678719,  0.17068415,  0.09740046]],

       [[ 0.48343202,  0.36808606,  0.17395177],
        [ 0.49963094,  0.32164782,  0.10467973],
        [ 0.28034237,  0.04529184,  0.38897793],
        ..., 
        [ 0.25209185,  0.14136379,  0.14376886],
        [ 0.15740206,  0.02332228,  0.22485095],
        [ 0.21098018,  0.13000661,  0.3129285 ]]])
In [ ]: