0% found this document useful (0 votes)
47 views

Introduction To Numerical Computing With Numpy Manual

This document provides an introduction to numerical computing with NumPy, the fundamental package for scientific computing with Python. It covers key NumPy concepts like arrays, indexing, slicing, array creation, calculation methods, broadcasting, and universal functions. The tutorial is presented over multiple sections, with examples demonstrating essential NumPy operations like arithmetic, indexing, shape manipulation, and formatting of numeric output.

Uploaded by

xexip31144
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
47 views

Introduction To Numerical Computing With Numpy Manual

This document provides an introduction to numerical computing with NumPy, the fundamental package for scientific computing with Python. It covers key NumPy concepts like arrays, indexing, slicing, array creation, calculation methods, broadcasting, and universal functions. The tutorial is presented over multiple sections, with examples demonstrating essential NumPy operations like arithmetic, indexing, shape manipulation, and formatting of numeric output.

Uploaded by

xexip31144
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Introduction to

Numerical Computing
with Numpy
Use Restrictions:

Use only permitted under license or agreement. Copying, sharing,


redistributing or other unauthorized use is strictly prohibited. The
Enthought Training Materials (ETM) are provided for the individual and sole
use of the paid attendee of the class ("Student”) for which the Training
Services are provided. The virtual training sessions may not be shared,
reproduced, transmitted, or retransmitted in any form or by any means,
electronic or mechanical, including photocopying, recording, or any
information storage and retrieval system. Furthermore, neither Customer nor
any Student shall:

Copy, disclose, transfer or distribute ETM to any party in any form. Remove,
modify or obscure any copyright, trademark, legal notices or other
proprietary notations in ETM. Make derivative works of ETM or combine ETM or
any part of ETM with any other works. Use ETM in any manner that could be
detrimental to Enthought. © 2001-2022, Enthought, Inc. All Rights
Reserved. All trademarks and registered trademarks are the property of their
respective owners.

Enthought, Inc. 200 W Cesar Chavez Suite 202 Austin, TX 78701


www.enthought.com

Q3-2022
letter
3.5.5
Introduction to Numerical Computing with
Numpy
Enthought, Inc.
www.enthought.com

Introduction 1
NumPy 2
Introducing NumPy Arrays 4
Multi-Dimensional Arrays 8
Slicing/Indexing Arrays 10
Fancy Indexing 16
Creating arrays 19
Array Creation Functions 21
Array Calculation Methods 24
Array Broadcasting 33
Universal Function Methods 41
The array data structure 48
Creating arrays 51
Closing words 56
Appendix 57
About Enthought 58
Introduction to
Numerical Computing
with NumPy
SciPy Conference Tutorial
2022

NumPy
The Standard Numerical Library
for Python

2
NumPy: The Standard Numerical Library for Python

Syllabus

1. Introducing Arrays
2. Indexing and Slicing
3. Creating Arrays
4. Array Calculations
5. The Array Data Structure
6. Structure Operations

a = 0 1 2 3

NumPy
Introducing Arrays

4
Introducing NumPy Arrays
SIMPLE ARRAY CREATION ARRAY SHAPE
>>> a = np.array([0, 1, 2, 3]) # Shape returns a tuple listing the
>>> a # length of the array along each
array([0, 1, 2, 3]) # dimension.
>>> a.shape
CHECKING THE TYPE (4,)
>>> type(a)
BYTES PER ELEMENT
numpy.ndarray
>>> a.itemize
NUMERIC "TYPE" OF ELEMENTS 4
>>> a.dtype
BYTES OF MEMORY USED
dtype('int32')
# Return the number of bytes used by
NUMBER OF DIMENSIONS # the data portion of the array.
>>> a.nbytes
>>> a.ndim
16
1

Array Operations
SIMPLE ARRAY MATH MATH FUNCTIONS
>>> a = np.array([1, 2, 3, 4]) # create array from 0.0 to 10.0
>>> b = np.array([2, 3, 4, 5]) >>> x = np.arange(11.0)
>>> a + b
array([3, 5, 7, 9]) # multiply entire array by scalar
# value
>>> a * b >>> c = (2.0 * np.pi) / 10.0
array([ 2, 6, 12, 20]) >>> c
0.62831853071795862
>>> a ** b >>> c * x
array([ 1, 8, 81, 1024]) array([0. , 0.628, …, 6.283])

# in-place operations
>>> x *= c
NumPy defines these constants: >>> x
pi = 3.14159265359 array([0. , 0.628, …, 6.283])
e = 2.71828182846
# apply functions to array
>>> y = np.sin(x)
6
Setting Array Elements
ARRAY INDEXING ! BEWARE OF TYPE COERCION
>>> a[0] >>> a.dtype
0 dtype('int32')

a 0 1 2 3 # assigning a float into an int32


# array truncates the decimal part
>>> a[0] = 10.6
index 0 1 2 3 >>> a
array([10, 1, 2, 3])
>>> a[0] = 10
>>> a # fill has the same behavior
array([10, 1, 2, 3]) >>> a.fill(-4.8)
>>> a
array([-4, -4, -4, -4])
a 10 1 2 3

index 0 1 2 3

Multi-Dimensional Arrays
MULTI-DIMENSIONAL ARRAYS ARRAY SHAPE
>>> a = np.array([[ 0, 1, 2, 3], >>> a[1, 3]
... [10,11,12,13]]) 13
column
>>> a 2D Array row
array([[ 0, 1, 2, 3], 0 1 2 3 >>> a[1, 3] = -1
a
[10,11,12,13]]) 10 11 12 13 >>> a
array([[ 0, 1, 2, 3],
SHAPE – (ROWS, COLUMNS) [10,11,12,-1]]) 0
a 1 0 1 2 3
>>> a.shape dim 1 4 10 11 12 -1
0 1 2 3
(2, 4) dim 0 a 2
10 11 12 13
0 1 2 3

ELEMENT COUNT ADDRESS SECOND (ONETH) ROW USING SINGLE INDEX

>>> a.size 4
>>> a[1]
0 1 2 3
8 2 x 4 = 8 a 2
10 11 12 13 array([10, 11, 12, -1])
0
0 1 2 3
NUMBER OF DIMENSIONS a 1
10 11 12 -1
>>> a.ndim dim 1 0 1 2 3
0 1 2 3
2 dim 0 a
10 11 12 13
8
Formatting Numeric Display
DEFAULT FORMATTING USER FORMATTING
>>> a = np.arange(1.0, 3.0, 0.5) # set precision
>>> a >>> np.set_printoptions(
array([1. , 1.5, 2. , 2.5]) precision=2)
>>> a
>>> a * np.pi
array([1. , 1.5, 2. , 2.5])
array([3.14159265, 4.71238898, 6.28318531,
7.85398163]) >>> a * np.pi
array([3.14, 4.71, 6.28, 7.85])
>>> a * np.pi * 1e8
>>> a * np.pi * 1e8
array([3.14159265e+08, 4.71238898e+08,
array([3.14e+08, 4.71e+08, 6.28e+08,
6.28318531e+08, 7.85398163e+08])
7.85e+08])
>>> a * np.pi * 1e-6 >>> a * np.pi * 1e-6
array([3.14159265e-06, 4.71238898e-06, array([3.14e-06, 4.71e-06, 6.28e-06,
6.28318531e-06, 7.85398163e-06]) 7.85e-06])
# suppress scientific notation
>>> np.set_printoptions(
suppress=True)
>>> a * np.pi * 1e-6
array([0., 0., 0., 0.])
9

0 1 2 3 4 5

0
0 1 2 3 4 5
1
10 11 12 13 14 15
2
20 21 22 23 24 25
3
30 31 32 33 34 35
4
40 41 42 43 44 45
5
50 51 52 53 54 55

NumPy
Indexing and Slicing

10
Slicing
var[lower:upper:step]
• Extracts a portion of a sequence by specifying a lower and upper bound.
• The lower-bound element is included, but the upper-bound element is not included.
• Mathematically: [lower, upper). The step value specifies the stride between elements.

SLICING ARRAYS OMITTING INDICES


# -5 -4 -3 -2 -1 # omitted boundaries are assumed to be
# indices: 0 1 2 3 4 # the beginning (or end) of the array
>>> a = np.array([10,11,12,13,14])
# grab first three elements
# [10, 11, 12, 13, 14] >>> a[:3]
>>> a[1:3] array([10, 11, 12])
array([11, 12])
# grab last two elements
# negative indices work also >>> a[-2:]
>>> a[1:-2] array([13, 14])
array([11, 12])
>>> a[-4:3] # every other element
array([11, 12]) >>> a[::2]
array([10, 12, 14])
11

Array Slicing
SLICING WORKS MUCH LIKE STANDARD
PYTHON SLICING
0 1 2 3 4 5
>>> a[0, 3:5]
array([3, 4]) 0
0 1 2 3 4 5
>>> a[4:, 4:] 1
10 11 12 13 14 15
array([[44, 45], 2
[54, 55]]) 20 21 22 23 24 25
3
>>> a[:, 2] 30 31 32 33 34 35
4
array([2, 12, 22, 32, 42, 52])
40 41 42 43 44 45
5
SLICING ARRAYS 50 51 52 53 54 55
>>> a[2::2, ::2]
array([[20, 22, 24],
[40, 42, 44]])

© 2008-2022 Enthought, Inc. 12


12
Assigning to a Slice
Slices are references to locations in memory.
These memory locations can be used in assignment operations.

>>> a = np.array([0, 1, 2, 3, 4])


# slicing the last two elements returns the data there
>>> a[-2:]
array([3, 4])
# we can insert an iterable of length two
>>> a[-2:] = [-1, -2]
>>> a
array([0, 1, 2, -1, -2])
# or a scalar value
>>> a[-2:] = 99
>>> a
array([0, 1, 2, 99, 99])
13

Give it a try!

Create the array below with the command

a = np.arange(25).reshape(5, 5)

and extract the slices as indicated.

0 1 2 3 4

0
0 1 2 3 4
1
5 6 7 8 9
2
10 11 12 13 14
3
15 16 17 18 19
4
20 21 22 23 24
5
© 2008-2022 Enthought, Inc. 14
14
Sliced Arrays Share Data
Arrays created by slicing share data with the originating array.
Changing values in a slice also changes the original array.

>>> a = np.array([0, 1, 2, 3, 4])

# create a slice containing two elements of a


>>> b = a[2:4]
>>> b
array([2, 3])
>>> b[0] = 10

# changing b changed a!
>>> a
array([ 0, 1, 10, 3, 4])
>>> np.shares_memory(a, b)
True
15

Fancy Indexing
INDEXING BY POSITION INDEXING WITH BOOLEANS
>>> a = np.arange(0, 80, 10) # manual creation of masks
>>> mask = np.array(
# fancy indexing ... [0, 1, 1, 0, 0, 1, 0, 0],
>>> indices = [1, 2, -3] ... dtype=bool)
>>> y = a[indices]
>>> y # fancy indexing
array([10, 20, 50]) >>> y = a[mask]
>>> y
# this also works with setting array([99, 99, 99])
>>> a[indices] = 99
>>> a
array([0, 99, 99, 30, 40, 99, 60, 70])
-3 -2 -1
0 1 2 3 4 5 6 7

a 0 10 20 30 40 50 60 70

y 10 20 50
16
Fancy Indexing in 2-D
>>> a[[0, 1, 2, 3, 4],
... [1, 2, 3, 4, 5]]
0 1 2 3 4 5
array([ 1, 12, 23, 34, 45])

>>> a[3:, [0, 2, 5]] 0


0 1 2 3 4 5
array([[30, 32, 35], 1
[40, 42, 45], 10 11 12 13 14 15
[50, 52, 55]]) 2
20 21 22 23 24 25
3
>>> mask = np.array( 30 31 32 33 34 35
... [1, 0, 1, 0, 0, 1], 4
... dtype=bool) 40 41 42 43 44 45
5
>>> a[mask, 2]
50 51 52 53 54 55
array([2, 22, 52])

Unlike slicing, fancy indexing creates copies


instead of a view into original array.

© 2008-2022 Enthought, Inc. 17


17

Give it a try!

1. Create the array below with


a = np.arange(25).reshape(5, 5)
and extract the elements indicated in blue.
2. Extract all the numbers divisible by 3 using a boolean mask.

0 1 2 3 4

0
0 1 2 3 4
1
5 6 7 8 9
2
10 11 12 13 14
3
15 16 17 18 19
4
20 21 22 23 24
5
© 2008-2022 Enthought, Inc. 18
18
arange()
linspace()
array()
zeros()
ones()

NumPy
Creating Arrays

© 2008-2022 Enthought, Inc. 19

Array Constructor Examples


FLOATING POINT ARRAYS ARRAY SHAPE
# Default to double precision >>> a = np.array([0,1,2,3],
>>> a = np.array([0,1.0,2,3]) ... dtype='uint8')
>>> a.dtype >>> a.dtype
dtype('float64') dtype('uint8')
>>> a.nbytes >>> a.nbytes
32 4

0 1 2 3

REDUCING PRECISION
a 0 1 2 3
>>> a = np.array([0,1.,2,3],
... dtype='float32') 1 byte 1 byte 1 byte 1 byte =4
>>> a.dtype
dtype('float32') Base 2 Base 10
>>> a.nbytes 00000000 -> 0 = 0*2**0 + 0*2**1 + ... + 0*2**7
16 00000001
00000010
->
->
1 = 1*2**0 + 0*2**1 + ... + 0*2**7
2 = 0*2**0 + 1*2**1 + ... + 0*2**7
...
11111111 -> 255 = 1*2**0 + 1*2**1 + ... + 1*2**7

© 2008-2022 Enthought, Inc. 20


Array Creation Functions
ARANGE ONES, ZEROS
arange([start,] stop[, step], ones(shape, dtype='float64')
dtype=None) zeros(shape, dtype='float64')
shape is a number or sequence specifying the
Nearly identical to Python’s range(). Creates an array
dimensions of the array. If dtype is not specified, it
of values in the range [start,stop) with the specified step
defaults to float64.
value. Allows non-integer values for start, stop, and
step. Default dtype is derived from the start, stop, and >>> np.ones((2, 3),
step values. ... dtype='float32')
array([[ 1., 1., 1.],
>>> np.arange(4) [ 1., 1., 1.]],
array([0, 1, 2, 3]) dtype=float32)
>>> np.arange(0, 2*pi, pi/4) >>> np.zeros(3)
array([ 0.000, 0.785, 1.571, 2.356, 3.142, array([ 0., 0., 0.]) 3
3.927, 4.712, 5.497])
0 1 2
3
0
# Be careful… 1. 1. 1.
2 1
>>> np.arange(1.5, 2.1, 0.3) 0. 0. 0.
1. 1. 1.
array([ 1.5, 1.8, 2.1])
dtype: float64
dtype: float32
zeros(3)is equivalent to zeros((3, ))

© 2008-2022 Enthought, Inc. 21

Array Creation Functions (cont'd)


IDENTITY EMPTY AND FULL
# Generate an n by n identity array. # empty(shape, dtype=float64,
# The default dtype is float64. # order='C')
>>> a = np.identity(4) >>> np.empty(2)
array([1.78021120e-306,
>>> a
6.95357225e-308])
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.], # array filled with 5.0
[ 0., 0., 1., 0.], >>> a = np.full(2, 5.0)
[ 0., 0., 0., 1.]]) array([5., 5.])
>>> a.dtype
dtype('float64') # alternative approaches
>>> np.identity(4, dtype=int) # (slower)
>>> a = np.empty(2)
array([[ 1, 0, 0, 0],
>>> a.fill(4.0)
[ 0, 1, 0, 0], >>> a
[ 0, 0, 1, 0], array([4., 4.])
[ 0, 0, 0, 1]]) >>> a[:] = 3.0
>>> a
array([3., 3.])

© 2008-2022 Enthought, Inc. 22


Array Creation Functions (cont'd)
LINSPACE ARRAYS FROM/TO TXT FILES
# Generate N evenly spaced elements
BEGINNING
BEGINNINGOFOFTHETHE
FILE
FILE
# between (and including) start and % Day, Month, Year, Skip, Avg Power
% Day, Month, Year, Skip, Avg Power
# stop values. 01, 01, 2000, x876, 13 % crazy day!
>>> np.linspace(0, 1, 5) %01,
we 01,
don’t2000, x876,
have Jan 13 % crazy day!
03rd
04, 01, 2000, xfed, 55 03rd
% we don’t have Jan
array([0., 0.25, 0.5, 0.75, 1.0]) 04, 01, 2000, xfed, 55
Data.txt

# loadtxt() automatically generates an


# array from the txt file
LOGSPACE arr = np.loadtxt('Data.txt',
# Generate N evenly spaced elements on ... skiprows=1,
# a log scale between base**start and ... dtype=int, delimiter=",",
# base**stop (default base=10) ... usecols = (0,1,2,4),
>>> np.logspace(0, 1, 5) ... comments = "%")
array([1., 1.78, 3.16, 5.62, 10.])
# Save an array into a txt file
np.savetxt('filename.txt', arr)
© 2008-2022 Enthought, Inc. 23

-1
1
0 -2
1 2 3 6
4 5 6 15

5 7 9

NumPy
Array Calculation Methods

24
Computations with Arrays

Operations between multiple array objects are


Rule 1:
first checked for proper shape match.

Mathematical operators (+ - * / exp, log, ...) apply


Rule 2:
element by element, on the values.

Reduction operations (mean, std, skew, kurt, sum, prod, ...)


Rule 3:
apply to the whole array, unless an axis is specified.

Missing values propagate unless explicitly ignored


Rule 4: (nanmean, nansum, ...).

25

Multi-Dimensional Arrays
VISUALIZING MULTI-DIMENSIONAL ARRAYS

0 1

0 1 2 3
0 1 2

(4,) (2, 4) (3, 2, 4) (2, 3, 2, 4)

-3 -3

-1 -1 -1 -1
-2 -2 -2

-4

26
Array Calculation
Methods 1 2 3
4 5 6
SUM METHOD
np.sum(a)
# Methods act on data stored in the array
>>> a = np.array([[1,2,3], -1
[4,5,6]]) 1
1 2 3
0 -2
# .sum() defaults to adding up all the
4 5 6
# values in an array.
>>> a.sum()
21 5 7 9
# supply the keyword axis to sum along the np.sum(a, axis=0)
# 0th axis -1
>>> a.sum(axis=0) 1
array([5, 7, 9]) 1 2 3 6
0 -2
# supply the keyword axis to sum along the 4 5 6 15
# last axis
np.sum(a, axis=-1)
>>> a.sum(axis=-1)
array([ 6, 15])
© 2008-2022 Enthought, Inc. 27
27

Other Operations on Arrays


SUM FUNCTION OTHER METHODS AND FUNCTIONS
# Functions work on data passed to it Mathematical functions
>>> a = np.array([[1,2,3], • sum, prod
[4,5,6]]) • min, max, argmin, argmax
• ptp (max – min)
# sum() defaults to adding up all
# values in an array. Statistics
>>> np.sum(a) • mean, std, var
21
Truth value testing
# supply an axis argument to sum along • any, all
# a specific axis
>>> np.sum(a, axis=0) See the NumPy appendix for more.
array([5, 7, 9])

28
Min/Max
MIN ARGMIN/MAX
>>> a = np.array([[2, 3], [0, 1]]) # Many tasks (like optimization) are
# Prefer NumPy functions to builtins when # interested in the location of a min/max,
# working with arrays # not the value
>>> np.min(a) >>> a.argmax()
0 1
# Most NumPy reducers can be used as
# methods as well as functions # arg methods return the location in a 1D,
>>> a.min() # flattened version of the original array
0 >>> np.argmin(a)
2
MAX UNRAVELING
# Use the axis keyword to find max values # NumPy includes a function to un-flatten
# for one dimension # 1D locations
>>> a.max(axis=0) >>> np.unravel_index(
array([2, 3]) ... a.argmax(), a.shape)
# as a function (0, 1)
>>> np.max(a, axis=1)
array([3, 1])

29

Where
COORDINATE LOCATIONS CONDITIONAL ARRAY CREATION
# NumPy's where function has two # Where can also be used to construct a new
# distinct uses. One is to provide # array by choosing values from other
# coordinates from masks. # arrays of the same shape.
>>> positives = np.arange(1, 5)
>>> a = np.arange(-2, 2) ** 2
>>> negatives = -positives
>>> a >>> np.where(mask, positives,
array([4, 1, 0, 1]) ... negatives)
>>> mask = a % 2 == 0 array([1, -2, 3, -4])
>>> mask
array([ True, False, True, False]) # Or from scalar values. This can be useful
# for recoding arrays.
# Coordinates are returned as a tuple >>> np.where(mask, 1, 0)
array([1, 0, 1, 0])
# of arrays, one for each axis.
>>> np.where(mask) # Or from both.
(array([0, 2]),) >>> np.where(mask, positives, 0)
array([1, 0, 3, 0])

30
Statistics Array Methods
MEAN STANDARD DEV./VARIANCE
>>> a = np.array([[1,2,3], # Standard Deviation
... [4,5,6]]) >>> a.std(axis=0)
array([ 1.5, 1.5, 1.5])
# mean value of each column # For sample, set ddof=1
>>> a.mean(axis=0) >>> a.std(axis=0, ddof=1)
array([ 2.5, 3.5, 4.5]) array([ 2.12, 2.12, 2.12])
>>> np.mean(a, axis=0)
array([ 2.5, 3.5, 4.5])
# variance
>>> a.var(axis=0)
array([2.25, 2.25, 2.25])
>>> np.var(a, axis=0)
array([2.25, 2.25, 2.25])

31

Give it a try!

Create the array below with


a = np.arange(-15, 15).reshape(5, 6) ** 2
and compute:
1. The maximum of each row
2. The mean of each column
3. The position of the overall minimum

0 1 2 3 4 5

0
225 196 169 144 121 100
1
81 64 49 36 25 16
2
9 4 1 0 1 4
3
9 16 25 36 49 64
4
81 100 121 144 169 196

© 2008-2022 Enthought, Inc. 32


32
a b y
0 0 0 0 1 2 0 1 2
10 10 10 0 1 2 10 11 12
20 20 20 + 0 1 2 = 20 21 22
30 30 30 0 1 2 30 31 32

NumPy
Array Broadcasting

© 2008-2022 Enthought, Inc. 33

Array Broadcasting
NumPy arrays of different dimensionality can be combined in the same expression. Arrays with smaller
dimension are broadcasted to match the larger arrays, without copying data.

Broadcasting has two rules.


RULE 1: PREPEND ONES TO SMALLER ARRAY'S SHAPE
>>> import numpy as np
>>> a = np.ones((3, 5)) # a.shape == (3, 5)
>>> b = np.ones((5,)) # b.shape == (5,)
>>> b.reshape(1, 5) # result is a (1,5)-shaped array
>>> b[np.newaxis, :] # equivalent, more concise

RULE 2: DIMENSIONS OF SIZE 1 ARE REPEATED WITHOUT COPYING


>>> c = a + b # c.shape == (3, 5)
# is logically equivalent to...
>>> tmp_b = b.reshape(1, 5)
>>> tmp_b_repeat = tmp_b.repeat(3, axis=0)
>>> c = a + tmp_b_repeat
# But broadcasting makes no copies of "b"s data!
© 2008-2022 Enthought, Inc. 34
Array Broadcasting
4x3 4x3 4x3 4x3
0 0 0 0 1 2 0 0 0 0 1 2
10 10 10 + 0 1 2 = 10 10 10 + 0 1 2 =
20 20 20 0 1 2 20 20 20 0 1 2
30 30 30 0 1 2 30 30 30 0 1 2

4x3 3
0 0 0 0 1 2 0 0 0 0 1 2 0 1 2
10 10 10 + = 10 10 10 + 0 1 2
= 10 11 12
20 20 20 20 20 20 0 1 2 20 21 22
30 30 30 30 30 30 0 1 2 30 31 32
stretch

4x1 3
0 0 1 2 0 0 0 0 1 2
10 + = 10 10 10 + 0 1 2 =
20 20 20 20 0 1 2
30 30 30 30 0 1 2 stretch

stretch
© 2008-2022 Enthought, Inc. 35

Broadcasting Rules
The trailing axes of either arrays must be 1 or both must have the same size for broadcasting to
occur.

Otherwise, a
"ValueError: shape mismatch: objects cannot be broadcast to a single shape"
exception is thrown.

4x3 Mismatch! 4

0 0 0 0 1 2 3
10 10 10 +
20 20 20
30 30 30

© 2008-2022 Enthought, Inc. 36


Broadcasting in Action
>>> a = array([0, 10, 20, 30])
>>> b = array([0, 1, 2])
>>> y = a[:, newaxis] + b

a b
4x1 3

0 0 0 0 1 2 0 1 2
10 10 10 + 0 1 2 = 10 11 12
20 20 20 0 1 2 20 21 22
30 30 30 0 1 2 30 31 32

stretch stretch

2-D Array 1-D Array

© 2008-2022 Enthought, Inc. 37

Application: Distance from Center

>>> import matplotlib.pyplot as plt


>>> a = np.linspace(0, 1, 15) - 0.5
>>> b = a[:, np.newaxis] # b.shape == (15, 1)
>>> dist2 = a**2 + b**2 # broadcasting sum.
>>> dist = np.sqrt(dist2)
>>> plt.imshow(dist)
>>> plt.colorbar()

© 2008-2022 Enthought, Inc. 38


Broadcasting's Usefulness
Broadcasting can often be used to replace needless data replication
inside a NumPy array expression.

np.meshgrid() – use newaxis appropriately in broadcasting expressions.

np.repeat() – broadcasting makes repeating an array along a dimension of size 1


unnecessary.

MESHGRID: COPIES DATA BROADCASTING: NO COPIES


>>> x, y = \ >>> x = np.array([1, 2])
... np.meshgrid([1,2], >>> y = np.array([3, 4, 5])
... [3,4,5]) >>> z = x[np.newaxis, :] \
>>> z = x + y ... + y[:, np.newaxis]

© 2008-2022 Enthought, Inc. 39

Broadcasting Indices
Broadcasting can also be used to slice elements from different “depths” in a 3-D
(or any other shape) array. This is a very powerful feature of indexing.

>>> data_cube = np.arange(27).reshape(3, 3, 3)


>>> yi, xi = np.meshgrid(np.arange(3), np.arange(3),
... sparse=True)
>>> zi = np.array([[0, 1, 2],
... [1, 1, 2],
... [2, 2, 2]])
>>> horizon = data_cube[xi, yi, zi]

Indices Selected Data


horizon
yi0 1 2 1 2
0
xi 0 0 1 2 1 1 2
1 0 1 2 2 2 2
2 0 1 2
zi data_cube © 2008-2022 Enthought, Inc. 40
1

0
3 0 1 2
33 10 11 12
63 20 21 22
93 30 31 32

NumPy
Universal Function Methods

© 2008-2022 Enthought, Inc. 41

Universal Function Methods


The mathematical, comparative, logical, and bitwise operators op that take two
arguments (binary operators) have special methods that operate on arrays:

>>> op.reduce(a,axis=0)
>>> op.accumulate(a,axis=0)
>>> op.outer(a,b)
>>> op.reduceat(a,indices)

© 2008-2022 Enthought, Inc. 42


op.reduce()
op.reduce(a) applies op to all the elements ADD EXAMPLE
in a 1-D array a reducing it to a single value. >>> a = np.array([1,2,3,4])
>>> np.add.reduce(a)
10
For example:
STRING LIST EXAMPLE
>>> a = np.array(['ab','cd','ef'],
... dtype='object')
yy = add.reduce
add.reduce(a)
(a) >>> np.add.reduce(a)
N −1
'abcdef'
=  a[n] LOGICAL OP EXAMPLES
n =0

= a[0] + a[1] + ... + a[ N − 1] >>> a = np.array([1,1,0,1])


>>> np.logical_and.reduce(a)
False
>>> np.logical_or.reduce(a)
True

© 2008-2022 Enthought, Inc. 43

op.reduce()
For multidimensional arrays, op.reduce(a,axis) applies op to the elements of a along the
specified axis. The resulting array has dimensionality one less than a. The default value for
axis is 0.
SUMMING UP EACH ROW SUM COLUMNS BY DEFAULT
>>> a = np.arange(3) + np.arange(0, 40, >>> np.add.reduce(a)
... 10).reshape(-1, 1) array([60, 64, 68])
>>> np.add.reduce(a,1)
array([ 3, 33, 63, 93])

1 1
60 64 68
0 0
3 0 1 2 0 1 2
33 10 11 12 10 11 12
63 20 21 22 21 22 23
93 30 31 32 30 31 32

© 2008-2022 Enthought, Inc. 44


op.accumulate()
op.accumulate(a) creates a new array ADD EXAMPLE
containing the intermediate results of the reduce
operation at each element in a. >>> a = np.array([1,2,3,4])
>>> np.add.accumulate(a)
array([ 1, 3, 6, 10])
For example: STRING LIST EXAMPLE
>>> a = np.array(['ab','cd','ef'],
... dtype='object')
yy = add.accumu
add.accumulate(a)
late(a) >>> np.add.accumulate(a)
array([ab,abcd,abcdef],
 0 1 N −1

=  a[n],  a[n],..., a[n] dtype=object)
 n =0 n =0 n =0  LOGICAL OP EXAMPLES
>>> a = np.array([1,1,0])
>>> np.logical_and.accumulate(a)
array([True, True, False])
>>> np.logical_or.accumulate(a)
array([True, True, True])
© 2008-2022 Enthought, Inc. 45

op.reduceat()
op.reduceat(a,indices) applies op to EXAMPLE
ranges in the 1-D array a defined by the values in >>> a = np.array([0,10,20,30,40,50])
indices. The resulting array has the same >>> indices = np.array([1,4])
>>> np.add.reduceat(a,indices)
length as indices. array([60, 90])

0 1 2 3 4 5
For example:

y = add.reduceat(a, indices) 0 10 20 30 40 50
indices[i + 1]
y[i] =  a[n]
n = indices[i]
For multidimensional arrays, reduceat() is always
Unlike
applied alongslicing,
the lastfancy indexing
axis (sum creates
of rows copies
for 2-D
! arrays). This is of
instead different fromoriginal
a view into the default
array.for
reduce() and accumulate().

© 2008-2022 Enthought, Inc. 46


op.outer()
op.outer(a,b) forms all possible combinations of elements between a and b using op. The
shape of the resulting array results from concatenating the shapes of a and b. (Order matters.)

a a[0] a[1] a[2] a[3] b b[0] b[1] b[2]

>>> np.add.outer(a,b) >>> np.add.outer(b,a)

a[0]+b[0] a[0]+b[1] a[0]+b[2]


b[0]+a[0] b[0]+a[1] b[0]+a[2] b[0]+a[3]
a[1]+b[0] a[1]+b[1] a[1]+b[2]
b[1]+a[0] b[1]+a[1] b[1]+a[2] b[1]+a[3]
a[2]+b[0] a[2]+b[1] a[2]+b[2]
b[2]+a[0] b[2]+a[1] b[2]+a[2] b[2]+a[3]
a30]+b[0] a[3]+b[1] a[3]+b[2]

© 2008-2022 Enthought, Inc. 47

Memory Block

0 1 2

8 bytes
24 bytes

NumPy
The Array Data Structure

48
Array Data Structure

Memory Block

0 1 2 3 4 5 6 7 8

0 1 2
Python View: 3 4 5
6 7 8
49

Array Data Structure

NDArray Data Structure


The int64 data type describes the
dtype * int64 array data elements
ndim 2
shape 3 3
Memory Block
strides 24 8
data * 0 1 2 3 4 5 6 7 8

8 bytes
24 bytes

0 1 2
Python View: 3 4 5
6 7 8
50
0 1
a 2 3

b 10 1 2 3

NumPy
Structure Operations

© 2008-2022 Enthought, Inc. 51

Operations on the Array Structure


Operations that only affect the array structure, not the data, can usually be
executed without copying memory.

>>> a = np.arange(6) >>> b = a.reshape(2, 3)


>>> a >>> b

Six Elements Three Columns

0 1 2
0 1 2 3 4 5
0
0 1 2 Two
a 0 1 2 3 4 5 b 1 Rows
3 4 5
This is not a new copy of the data.
The original data does not get reordered.
© 2008-2022 Enthought, Inc. 52
52
Transpose
TRANSPOSE TRANSPOSE RETURNS VIEWS
>>> a = np.array([[0,1,2], # Transpose does not move values around in
... [3,4,5]]) # memory. It only changes the order of
>>> a.shape # "strides" in the array
(2,3) >>> a.strides
(24, 8)
# Transpose swaps the order of axes. >>> a.T.strides
>>> a.T (8, 24)
array([[0, 3], Memory Block

[1, 4], 8
24

[2, 5]]) 0 1 2 3 4 5
>>> a.T.shape
(3,2) 8 bytes
24 bytes
Two Columns
Three Columns 3 2
0 1 strides 24 8 strides 8 24
0 1 2 0 24
8
a 1 0 3 Three
0 Two 0 1 2 8 0 3
a 0 1 2 1 4 Rows 2 24
1 Rows 2 3 4 5 3 1 4
3 4 5 2 5
2x3 2 5

3x2

© 2008-2022 Enthought, Inc. 53

Reshaping Arrays
RESHAPE SHAPE
>>> a = np.array([[0,1,2], >>> a = np.arange(6)
... [3,4,5]]) >>> a
array([0, 1, 2, 3, 4, 5])
# Return a new array with a different shape >>> a.shape
# (a view where possible) (6,)
>>> a.reshape(3,2)
array([[0, 1], # Reshape array in-place to 2x3
[2, 3], >>> a.shape = (2,3)
[4, 5]]) >>> a
array([[0, 1, 2],
# Reshape cannot change the number of [3, 4, 5]])
# elements in an array
>>> a.reshape(4,2)
ValueError: total size of new array must be Six Elements Three Columns

unchanged
0 1 2
0 1 2 3 4 5
0
0 1 2 Two
a 1 Rows
0 1 2 3 4 5 3 4 5

54
Flattening Arrays
FLATTEN (SAFE) RAVEL (EFFICIENT)
a.flatten() converts a multi-dimensional array a.ravel() is the same as a.flatten(), but
into a 1-D array. The new array is a copy of the returns a reference (or view) of the array if possible
original data. (i.e., the memory is contiguous). Otherwise the new
array copies the data.
# Create a 2D array np.ravel() can be applied to non-array objects.
>>> a = np.array([[0,1],
... [2,3]]) # Flatten out elements to 1-D
# Flatten out elements to 1D >>> b = a.ravel()
>>> b = a.flatten() >>> b
>>> b array([0,1,2,3])
array([0,1,2,3])
# Changing b does change a
# Changing b does not change a >>> b[0] = 10
>>> b[0] = 10 >>> b
>>> b array([10,1,2,3])
array([10,1,2,3]) b 10 1 2 3 >>> a changed! b 10 1 2 3
>>> a no change
0 1 array([[10, 1], 10 1
array([[0, 1], a 2 3 [ 2, 3]])
a 2 3
[2, 3]])
© 2008-2022 Enthought, Inc. 55

Stay in touch!

Enthought
Enthought @enthought
Media

EuroSciPy

Please complete the online survey!


(link on course web page)
© 2008-2022 Enthought, Inc. 56
Appendix
Additional Material

57

Enthought powers
digital transformation
for science.

Confidential and Proprietary 58


We Partner with Industry Leaders

Confidential and Proprietary 59

ABOUT ENTHOUGHT

Foundation for Success

● Global, privately-owned company with


headquarters in Austin
● Offices in Houston, Texas; Cambridge,
United Kingdom; Zürich, Switzerland;
and Tokyo, Japan
● Deep roots in the Python community
of scientists and engineers
● 80% of employees have graduate
degrees or PhDs in science and
engineering

Confidential and Proprietary Confidential and Proprietary 60


About Enthought

Partner with Enthought


Science is at the core of your business. And ours.
Designed by scientists, for scientists

The Enthought Approach is proven.


Catalyzing innovation by transforming technology, people, and processes

We’re at the intersection of science and technology.


Deep scientific expertise and computational knowledge

We empower scientists.
Equipping scientists with digital skills and technology

Confidential and Proprietary 61

Confidential and Proprietary 62

You might also like