Numpy Basics

Chris Calloway

UNC Renaissance Computing Institute (RENCI)

A word about me.

My name is Chris Calloway.

I'm an Applications Analyst at RENCI (a UNC System research institute in Chapel Hill).

I work with marine data, especially hurricane model data.

I also volunteer my time to the Triangle Python Users Group (TriPython).

My email is cbc@unc.edu.

Sidebar

BTW, TriPython and Research Triangle Analysts are working together to bring PyData, a 400-person conference about data science with Python, to IBM RTP, September 14-16. It will be epic.

A word about the topic.

This talk is basic.

It is about a Python package called NumPy.

NumPy is used by most all Python data science packages.

So you need to know NumPy fairly thoroughly to be moderately proficient at data science with Python.

These are the basics about a very basic package.

A word about this talk.

It will go quickly.

It is using Jupyter, an through-the-browser interactive and collaborative environment for data science.

Jupyter used to be called "Ipython Notebook," if you've heard of that.

Jupyter stands for "Julia, Python and R." But Jupyter works with all kinds of back ends, such as Matlab.

With Jupyter, you create "notebooks," a sequence of code, text, and graphic "cells" which tell a data science story.

I convert my notebook for this talk into a reveal.js presentation of static slides with a Jupyter tool called nbconvert.

You can get ths interactive notebook and follow along at http://tinyurl.com/af16numpy

A word about Python.

This talk is in Python 3.

If you run this notebook yourself, you will need Python 3.

Python 2 is just as useful and works 95% the same as Python 3.

I hate to quibble about which Python is best. They are both great and both do data science well.

Python is easy to install, especially if you get a distribution of Python from python.org.

However, some Python data science tools can be very hard to install on top of the Python from python.org.

Some require you to have very specific C++ and Fortran compilers as well as linear algebra libraries compiled with special flags in order to work efficiently.

That can be doubly hard on Windows.

The best solution is to get a Python distribution that already has the data science tools pre-bundled for your OS.

This will save you a lot of time and leverage the work of data science tool packaging experts.

The best such distribution is Anaconda from Continuum Analytics. See http://continuum.io

Python lists are a lot like Python arrays.

  • Lists, like arrays, are ORDERED collections of objects.

  • Many, but not all, things you can do with lists, you can do with arrays.

Create an unbound empty list

  • from a literal representation
In [1]:
[]
Out[1]:
[]

Create an unbound list

  • with the built-in list object
  • using any collection type an an argument
  • such as a string
In [2]:
list("Jupyter")
Out[2]:
['J', 'u', 'p', 'y', 't', 'e', 'r']

Create a list

  • bound to the identifier "lst"
  • from a literal representation
In [3]:
lst = [1, 2, 3,]
print(lst)
[1, 2, 3]

Most list manipulation occurs with the subscription operator: [ ]

  • And a zero-based INDEX.

Access an ELEMENT of a list

  • lists are ZERO-BASED
  • second element of the list
In [4]:
lst[1]
Out[4]:
2

First element

In [5]:
lst[0]
Out[5]:
1

Last element

In [6]:
lst[-1]
Out[6]:
3

List Mutation

Add an element

  • Can't do this with arrays
  • Arrays are fixed length
In [7]:
lst.append(100)
print(lst)
[1, 2, 3, 100]

List Mutation

Change (or replace or set) an element

  • Only possible array mutation
  • Doesn't change the length of the collection
In [8]:
lst[1] = 5
print(lst)
[1, 5, 3, 100]

List Mutation

Delete an element

  • Can't do this with arrays
  • Arrays are fixed length
In [9]:
del lst[2]
print(lst)
[1, 5, 100]

Concatenate lists

  • Makes a new list object
In [10]:
[1, 2, 3,] + [11, 12, 13,]
Out[10]:
[1, 2, 3, 11, 12, 13]

Repeat a list

  • Makes a new list object
In [11]:
[1, 2, 3,] * 5
Out[11]:
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

Slice a list

  • Makes a new list object
In [12]:
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,]
lst[2:7]
Out[12]:
[3, 4, 5, 6, 7]

Slice lists stepwise

In [13]:
lst[1:10:3]
Out[13]:
[2, 5, 8]

Slice backwards

In [14]:
lst[9:2:-3]
Out[14]:
[10, 7, 4]

Slice the the end of the list

In [15]:
lst[5:]
Out[15]:
[6, 7, 8, 9, 10]

Slice up to an index

In [16]:
lst[:5]
Out[16]:
[1, 2, 3, 4, 5]

List Mutation

Replace a slice with another

  • ARBITRARY size
In [17]:
lst[2:7] = [-1, -2, -3]
print(lst)
[1, 2, -1, -2, -3, 8, 9, 10]

List Mutation

Replace a slice stepwise

  • SIZE MUST MATCH!
In [18]:
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,]
lst[1:10:3] = [-1, -2, -3]
print(lst)
[1, -1, 3, 4, -2, 6, 7, -3, 9, 10]

Make a copy of a list

  • A copy can be independently mutated
In [19]:
newlist = lst[:]
print(newlist)
print("Same object?", newlist is lst)
print("Equivalent objects?", newlist == lst)
[1, -1, 3, 4, -2, 6, 7, -3, 9, 10]
Same object? False
Equivalent objects? True

Make a multidimensional list of lists

  • Rows may be different sizes
  • Unlike multidimensional arrays
In [20]:
lst2d = [[1, 2, 3],
         [4, 5, 6, 7],
         [8, 9, 10, 11, 12],]
print(lst2d)
print(lst2d[1][2])
[[1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11, 12]]
6

The main difference between lists and arrays?

  • lists are HETEROGENEOUS
  • ordered collections of objects
  • of ARBITRARY data types
In [21]:
lst = [False, 1, 2.0, 3+4j, "five", min, None]
for element in lst:
    print(type(element)),
<class 'bool'>
<class 'int'>
<class 'float'>
<class 'complex'>
<class 'str'>
<class 'builtin_function_or_method'>
<class 'NoneType'>

Arrays are Homogeneous

  • ordered collections of objects
  • of the SAME data type
  • Arrays are also fixed size
    • No additional cells
    • No cell deletion
  • For a multidimesional array
    • the dimension of each axis
    • fixed at array creation

The numpy package

  • Implements Python arrays
  • The np identifier is conventional
In [22]:
import numpy as np

The np.array function

  • takes an object
  • which implements the ARRAY PROTOCOL
    • collections which can get and set elements
    • all the same data type
    • equal length rows
  • as an argument
  • such as a list or another array
In [23]:
arr = np.array([10, 20, 30, 40,])
print(arr)
arr
[10 20 30 40]
Out[23]:
array([10, 20, 30, 40])

Access a CELL of an array

  • ZERO-BASED
In [24]:
arr[2]
Out[24]:
30

First cell

In [25]:
arr[0]
Out[25]:
10

Last cell

In [26]:
arr[-1]
Out[26]:
40

A Slice of cells

  • Does not create a copy
  • Creates a VIEW
In [27]:
barr = arr[1:3]
print(barr)
[20 30]
  • Changes to the view
    • Are reflected in the parent
    • And vice-versa
In [28]:
barr[0] = 1000
print(arr)
[  10 1000   30   40]

Stepwise slice

In [29]:
arr[::2]
Out[29]:
array([10, 30])

Replace a slice

  • SIZE MUST MATCH!
In [30]:
arr[1:3] = np.array([50, 60])
print(arr)
[10 50 60 40]

Replace a slice stepwise

  • SIZE MUST MATCH!
In [31]:
arr[::2] = np.array([70, 80])
print(arr)
[70 50 80 40]

Handy Attributes: dtype

In [32]:
arr.dtype
Out[32]:
dtype('int64')
In [33]:
arr = np.array([10., 20., 30., 40.,])
arr.dtype
Out[33]:
dtype('float64')
In [34]:
arr = np.array([10., 20., 30., 40.,], dtype=np.complex128)
arr.dtype
arr
Out[34]:
array([ 10.+0.j,  20.+0.j,  30.+0.j,  40.+0.j])

List of simple dtypes

In [35]:
np.sctypes
Out[35]:
{'complex': [numpy.complex64, numpy.complex128, numpy.complex256],
 'float': [numpy.float16, numpy.float32, numpy.float64, numpy.float128],
 'int': [numpy.int8, numpy.int16, numpy.int32, numpy.int64],
 'others': [bool, object, str, str, numpy.void],
 'uint': [numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64]}

Handy Attributes: ndim

In [36]:
arr.ndim
Out[36]:
1
In [37]:
arr2 = np.array([[1, 2, 3,], [4, 5 ,6,], [7, 8, 9]])
print(arr2) 
arr2.ndim
[[1 2 3]
 [4 5 6]
 [7 8 9]]
Out[37]:
2

Handy Attributes: ndim

In [38]:
arr3 = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
                 [[11, 12, 13], [14, 15, 16], [17, 18, 19]]])
print(arr3)
arr3.ndim
[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[11 12 13]
  [14 15 16]
  [17 18 19]]]
Out[38]:
3

Handy Attributes: shape

In [39]:
arr.shape
Out[39]:
(4,)
In [40]:
arr2.shape
Out[40]:
(3, 3)
In [41]:
arr3.shape
Out[41]:
(2, 3, 3)

Handy Attributes: size

In [42]:
arr.size
Out[42]:
4
In [43]:
arr2.size
Out[43]:
9
In [44]:
arr3.size
Out[44]:
18

Handy Attributes: itemsize

In [45]:
u8arr = arr = np.array([2, 3, 5], dtype=np.uint8)
u8arr.itemsize
Out[45]:
1
In [46]:
iarr = arr = np.array([2, 3, 5], dtype=np.int)
iarr.itemsize
Out[46]:
8
In [47]:
farr = arr = np.array([2, 3, 5], dtype=np.float128)
farr.itemsize
Out[47]:
16

Handy Attributes: nbytes

In [48]:
u8arr.nbytes
Out[48]:
3
In [49]:
iarr.nbytes
Out[49]:
24
In [50]:
farr.nbytes
Out[50]:
48

Handy Attributes: base

In [51]:
print(arr2)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
In [52]:
varr2 = arr2[2:]
print(varr2)
[[7 8 9]]
In [53]:
print(varr2.base)
[[1 2 3]
 [4 5 6]
 [7 8 9]]

Handy Attributes: T (for Transpose)

In [54]:
print(arr2)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
In [55]:
print(arr2.T)
[[1 4 7]
 [2 5 8]
 [3 6 9]]
In [56]:
arr2.T[1,1] = 50
print(arr2)
[[ 1  2  3]
 [ 4 50  6]
 [ 7  8  9]]

Handy Attributes: flat

  • Evaluates to an iterator
In [57]:
for x in arr3.flat: print(x, end=" ")
1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 

Handy Functions: zeros

  • First argument: shape tuple
  • Must specify a dtype
In [58]:
np.zeros((2, 3, 4 ), dtype=np.int)
Out[58]:
array([[[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]])
In [59]:
np.zeros((2, 3, 4), dtype=np.int) + 4
Out[59]:
array([[[4, 4, 4, 4],
        [4, 4, 4, 4],
        [4, 4, 4, 4]],

       [[4, 4, 4, 4],
        [4, 4, 4, 4],
        [4, 4, 4, 4]]])

Handy Functions: empty

  • Only marginally faster than zeros
  • Does not clear memory like zeros
  • Contents of cells are unpredictable
In [60]:
np.empty((2, 3, 4), dtype=np.int)
Out[60]:
array([[[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]],

       [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]])

Handy Functions: ones

In [61]:
np.ones((2, 3, 4), dtype=np.int)
Out[61]:
array([[[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]],

       [[1, 1, 1, 1],
        [1, 1, 1, 1],
        [1, 1, 1, 1]]])
In [62]:
np.ones((2, 3, 4), dtype=np.int) * 5
Out[62]:
array([[[5, 5, 5, 5],
        [5, 5, 5, 5],
        [5, 5, 5, 5]],

       [[5, 5, 5, 5],
        [5, 5, 5, 5],
        [5, 5, 5, 5]]])

Handy Functions: arange

Stop argument

In [63]:
np.arange(10, dtype=np.float)
Out[63]:
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])

Start and stop arguments

In [64]:
np.arange(5, 13, dtype=np.int64)
Out[64]:
array([ 5,  6,  7,  8,  9, 10, 11, 12])

Start, stop, and step arguments

In [65]:
np.arange(21, 50, 3, dtype=np.complex)
Out[65]:
array([ 21.+0.j,  24.+0.j,  27.+0.j,  30.+0.j,  33.+0.j,  36.+0.j,
        39.+0.j,  42.+0.j,  45.+0.j,  48.+0.j])

Handy Functions: fill

In [66]:
empty = np.empty((2, 2), dtype=np.float)
empty.fill(np.nan)
empty
Out[66]:
array([[ nan,  nan],
       [ nan,  nan]])
In [67]:
empty = np.empty((2, 2), dtype=np.float)
empty.fill(np.pi)
empty
Out[67]:
array([[ 3.14159265,  3.14159265],
       [ 3.14159265,  3.14159265]])

Handy Functions: linspace and logspace

In [68]:
np.linspace(2, 3, 6)
Out[68]:
array([ 2. ,  2.2,  2.4,  2.6,  2.8,  3. ])
In [69]:
np.logspace(2, 6, 5)
Out[69]:
array([  1.00000000e+02,   1.00000000e+03,   1.00000000e+04,
         1.00000000e+05,   1.00000000e+06])
In [70]:
np.logspace(2, 6, 5, base=np.e)
Out[70]:
array([   7.3890561 ,   20.08553692,   54.59815003,  148.4131591 ,
        403.42879349])

Handy Functions: numpy.random.random

  • Only argument: shape tuple
  • Random samples
  • From a uniform distribution
  • Between 0 and 1
In [71]:
import numpy.random as npr

npr.random((3,3))
Out[71]:
array([[  8.94385821e-01,   8.10642156e-01,   3.27138140e-01],
       [  9.17701774e-01,   9.48010691e-01,   5.98324523e-05],
       [  4.10223737e-02,   1.78011501e-02,   5.29260792e-01]])

Handy Functions: numpy.random.randn

  • Arguments: dimensions
  • Random samples
  • From a normal distribution
  • Median of 0
  • Variance of 1
In [72]:
npr.randn(3,3)
Out[72]:
array([[ 2.68109214,  0.57919619, -0.18174461],
       [-0.26585964, -0.16735464, -0.60191097],
       [-0.27533449,  0.51488905, -0.32429089]])

Handy Functions: numpy.random.normal

  • First argument: median
  • Second argument: variance
  • Third argument: shape tuple
  • From a normal distribution
In [73]:
npr.normal(10, 3, (3, 3))
Out[73]:
array([[  2.08898702,  12.09836513,   6.08891988],
       [ 15.69283062,  13.52268888,  13.77205018],
       [ 11.81720951,  11.71298632,   4.75654573]])

Handy Functions: identity

In [74]:
np.identity(4)
Out[74]:
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])
In [75]:
np.eye(4)
Out[75]:
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])

Handy Methods: reshape

In [76]:
linear = np.linspace(2, 12, 24)
print(linear)
[  2.           2.43478261   2.86956522   3.30434783   3.73913043
   4.17391304   4.60869565   5.04347826   5.47826087   5.91304348
   6.34782609   6.7826087    7.2173913    7.65217391   8.08695652
   8.52173913   8.95652174   9.39130435   9.82608696  10.26086957
  10.69565217  11.13043478  11.56521739  12.        ]
In [77]:
print(linear.reshape(3, 8))
[[  2.           2.43478261   2.86956522   3.30434783   3.73913043
    4.17391304   4.60869565   5.04347826]
 [  5.47826087   5.91304348   6.34782609   6.7826087    7.2173913
    7.65217391   8.08695652   8.52173913]
 [  8.95652174   9.39130435   9.82608696  10.26086957  10.69565217
   11.13043478  11.56521739  12.        ]]

Handy Methods: reshape

  • Reshape returns a view!
In [78]:
print(linear.reshape(8, 3))
[[  2.           2.43478261   2.86956522]
 [  3.30434783   3.73913043   4.17391304]
 [  4.60869565   5.04347826   5.47826087]
 [  5.91304348   6.34782609   6.7826087 ]
 [  7.2173913    7.65217391   8.08695652]
 [  8.52173913   8.95652174   9.39130435]
 [  9.82608696  10.26086957  10.69565217]
 [ 11.13043478  11.56521739  12.        ]]

Handy Methods: sum and prod

In [79]:
linear.sum()
Out[79]:
168.0
In [80]:
linear.prod()
Out[80]:
1.2458126737356677e+19

Handy Methods: cumsum and cumprod

In [81]:
print(linear.cumsum())
[   2.            4.43478261    7.30434783   10.60869565   14.34782609
   18.52173913   23.13043478   28.17391304   33.65217391   39.56521739
   45.91304348   52.69565217   59.91304348   67.56521739   75.65217391
   84.17391304   93.13043478  102.52173913  112.34782609  122.60869565
  133.30434783  144.43478261  156.          168.        ]
In [82]:
print(linear.cumprod())
[  2.00000000e+00   4.86956522e+00   1.39735350e+01   4.61734199e+01
   1.72648440e+02   7.20619574e+02   3.32111630e+03   1.67499779e+04
   9.17607482e+04   5.42585294e+05   3.44423708e+06   2.33609124e+07
   1.68604846e+08   1.29019360e+09   1.04337396e+10   8.89136068e+10
   7.96356653e+11   7.47882769e+12   7.34876113e+13   7.54046794e+14
   8.06502223e+15   8.97672039e+16   1.03817723e+18   1.24581267e+19]

Handy Methods: max, min, mean, and ptp

In [83]:
linear.max()
Out[83]:
12.0
In [84]:
linear.min()
Out[84]:
2.0
In [85]:
linear.mean()
Out[85]:
7.0
In [86]:
linear.ptp()
Out[86]:
10.0

Handy Methods: round, std, and var

In [87]:
linear.round()
Out[87]:
array([  2.,   2.,   3.,   3.,   4.,   4.,   5.,   5.,   5.,   6.,   6.,
         7.,   7.,   8.,   8.,   9.,   9.,   9.,  10.,  10.,  11.,  11.,
        12.,  12.])
In [88]:
linear.std()
Out[88]:
3.00964632714423
In [89]:
linear.var()
Out[89]:
9.0579710144927521

Array Operations Are Element-wise

In [90]:
np.array([1, 2, 3]) + np.array([4, 5, 6])
Out[90]:
array([5, 7, 9])
In [91]:
np.array([1, 2, 3]) * np.array([4, 5, 6])
Out[91]:
array([ 4, 10, 18])

Numpy Ufuncs: Operations As Functions

In [92]:
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
np.add(arr1, arr2)
Out[92]:
array([5, 7, 9])
In [93]:
np.multiply(arr1, arr2)
Out[93]:
array([ 4, 10, 18])

Math Unfuncs

add floor_divide rint log10
subtract negative sign expm1
multiply power conj log1p
divide remainder exp sqrt
logaddexp mod exp2 square
logaddexp2 fmod log reciprocal
true_divide absolute log2 ones_like

Trig Ufuncs

sin arccos sinh arccosh
cos arctan cosh arctanh
tan arctan2 tanh deg2rad
arcsin hypot arcsinh rad2deg

Ufuncs For

  • Bitwise operations
  • Comparison operations
  • Logical operations
  • Distribution operations
  • Floating point operations
    • isnan
    • isinf
    • ceil

Ufuncs are Universally Useful

In [94]:
%matplotlib inline
import matplotlib.pyplot as plt

linear = np.linspace(0, 10 * np.pi, 1000)
sine = np.sin(linear ** 1.5)
plt.plot(sine)
Out[94]:
[<matplotlib.lines.Line2D at 0x10e6d2978>]

Vectorize: Create Your Own Ufuncs

In [95]:
def f(x):
    return (x ** 5) - (x ** 4) + (x ** 3) - (x ** 2) + x - 5

vf = np.vectorize(f)
linear = np.linspace(-10, 10, 100)
solution = vf(linear)
plt.plot(solution)
Out[95]:
[<matplotlib.lines.Line2D at 0x10eb55dd8>]

Array Indexing

In [96]:
linear = np.linspace(0, 4 * np.pi, 100)
sine = np.sin(linear)
positive = sine > 0
positive
Out[96]:
array([False,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False, False], dtype=bool)
In [97]:
sine
Out[97]:
array([  0.00000000e+00,   1.26592454e-01,   2.51147987e-01,
         3.71662456e-01,   4.86196736e-01,   5.92907929e-01,
         6.90079011e-01,   7.76146464e-01,   8.49725430e-01,
         9.09631995e-01,   9.54902241e-01,   9.84807753e-01,
         9.98867339e-01,   9.96854776e-01,   9.78802446e-01,
         9.45000819e-01,   8.95993774e-01,   8.32569855e-01,
         7.55749574e-01,   6.66769001e-01,   5.67059864e-01,
         4.58226522e-01,   3.42020143e-01,   2.20310533e-01,
         9.50560433e-02,  -3.17279335e-02,  -1.58001396e-01,
        -2.81732557e-01,  -4.00930535e-01,  -5.13677392e-01,
        -6.18158986e-01,  -7.12694171e-01,  -7.95761841e-01,
        -8.66025404e-01,  -9.22354294e-01,  -9.63842159e-01,
        -9.89821442e-01,  -9.99874128e-01,  -9.93838464e-01,
        -9.71811568e-01,  -9.34147860e-01,  -8.81453363e-01,
        -8.14575952e-01,  -7.34591709e-01,  -6.42787610e-01,
        -5.40640817e-01,  -4.29794912e-01,  -3.12033446e-01,
        -1.89251244e-01,  -6.34239197e-02,   6.34239197e-02,
         1.89251244e-01,   3.12033446e-01,   4.29794912e-01,
         5.40640817e-01,   6.42787610e-01,   7.34591709e-01,
         8.14575952e-01,   8.81453363e-01,   9.34147860e-01,
         9.71811568e-01,   9.93838464e-01,   9.99874128e-01,
         9.89821442e-01,   9.63842159e-01,   9.22354294e-01,
         8.66025404e-01,   7.95761841e-01,   7.12694171e-01,
         6.18158986e-01,   5.13677392e-01,   4.00930535e-01,
         2.81732557e-01,   1.58001396e-01,   3.17279335e-02,
        -9.50560433e-02,  -2.20310533e-01,  -3.42020143e-01,
        -4.58226522e-01,  -5.67059864e-01,  -6.66769001e-01,
        -7.55749574e-01,  -8.32569855e-01,  -8.95993774e-01,
        -9.45000819e-01,  -9.78802446e-01,  -9.96854776e-01,
        -9.98867339e-01,  -9.84807753e-01,  -9.54902241e-01,
        -9.09631995e-01,  -8.49725430e-01,  -7.76146464e-01,
        -6.90079011e-01,  -5.92907929e-01,  -4.86196736e-01,
        -3.71662456e-01,  -2.51147987e-01,  -1.26592454e-01,
        -4.89858720e-16])

Masking: Index An Array With An Array Of Bools

In [98]:
sine[positive]
Out[98]:
array([ 0.12659245,  0.25114799,  0.37166246,  0.48619674,  0.59290793,
        0.69007901,  0.77614646,  0.84972543,  0.909632  ,  0.95490224,
        0.98480775,  0.99886734,  0.99685478,  0.97880245,  0.94500082,
        0.89599377,  0.83256985,  0.75574957,  0.666769  ,  0.56705986,
        0.45822652,  0.34202014,  0.22031053,  0.09505604,  0.06342392,
        0.18925124,  0.31203345,  0.42979491,  0.54064082,  0.64278761,
        0.73459171,  0.81457595,  0.88145336,  0.93414786,  0.97181157,
        0.99383846,  0.99987413,  0.98982144,  0.96384216,  0.92235429,
        0.8660254 ,  0.79576184,  0.71269417,  0.61815899,  0.51367739,
        0.40093054,  0.28173256,  0.1580014 ,  0.03172793])

Ellipsis: Filling In For Missing Indices

In [99]:
linear = np.linspace(1,100000,100000, dtype=np.int)
linear5 = linear.reshape((10,10,10,10,10))
linear5[9, 9, ... , 9, 9]
Out[99]:
array([ 99100,  99200,  99300,  99400,  99500,  99600,  99700,  99800,
        99900, 100000])

Linear algebra

In [100]:
arr1 = np.logspace(0, 1, 9, base=np.pi)
arr2 = arr1[::-1]
np.dot(arr1, arr2)
Out[100]:
28.274333882308138
In [101]:
arr1 = np.logspace(0, 1, 9, base=np.pi)
arr1 = arr1.reshape((3,3))
np.dot(arr1, arr1.T)
Out[101]:
array([[  4.10378921,   6.30400063,   9.68383654],
       [  6.30400063,   9.68383654,  14.87574252],
       [  9.68383654,  14.87574252,  22.85124438]])

More

  • cross
  • vdot
  • inner
  • outer
  • matmul
  • tensordot
  • einsum
  • kron

numpy.linalg: Decompositions

  • matrix_power
  • cholesky
  • qr
  • svd

numpy.linalg: Eigenvalues And Eigenvectors

  • eig
  • eigh
  • eigvals
  • eigvalsh

numpy.linalg: Norms, Determinants, Conditions, Ranks

  • norm
  • cond
  • det
  • matrix_rank
  • slogdet
  • trace

numpy.linalg: Equation Solutions

  • solve
  • tensorsolve
  • lstsq
  • inv
  • pinv
  • tensorinv

Other Numpy Subpackages

  • Fourier and other transforms
  • Financial functions
  • Statistical functions
  • Grid functions
  • Masking functions
  • Set functions
  • Sorting and searching

numpy.org: From The Tutorial

In [102]:
def mandelbrot( h,w, maxit=20 ):
    """Returns an image of the Mandelbrot fractal of size (h,w)."""
    y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
    c = x+y*1j
    z = c
    divtime = maxit + np.zeros(z.shape, dtype=int)

    for i in range(maxit):
        z = z**2 + c
        diverge = z*np.conj(z) > 2**2         # who is diverging
        div_now = diverge & (divtime==maxit)  # who is diverging now
        divtime[div_now] = i                  # note when
        z[diverge] = 2                        # avoid diverging too much

    return divtime

plt.imshow(mandelbrot(400,400))
plt.show()