NumPy¶
The NumPy package provides the "ndarray" object. The NumPy array is used to contain data of uniform type with an arbitrary number of dimensions. NumPy then provides basic mathematical and array methods to lay down the foundation for the entire SciPy ecosystem. The following import statement is the generally accepted convention for NumPy.
import numpy as np
Array Creation¶
There are several ways to make NumPy arrays. An array has three particular attributes that can be queried: shape, size and the number of dimensions.
a = np.array([1, 2, 3])
print a.shape
print a.size
print a.ndim
x = np.arange(100)
print x.shape
print x.size
print x.ndim
y = np.random.rand(5, 80)
print y.shape
print y.size
print y.ndim
Array Manipulation¶
How to change the shape of an array without a copy!
x.shape = (20, 5)
print x
NumPy can even automatically figure out the size of at most one dimension for you.
y.shape = (4, 20, -1)
print y.shape
Array Indexing¶
# Scalar Indexing
print x[2]
# Slicing
print x[2:5]
# Advanced slicing
print "First 5 rows\n", x[:5]
print "Row 18 to the end\n", x[18:]
print "Last 5 rows\n", x[-5:]
print "Reverse the rows\n", x[::-1]
# Boolean Indexing
print x[(x % 2) == 0]
# Fancy Indexing -- Note the use of a list, not tuple!
print x[[1, 3, 8, 9, 2]]
Broadcasting¶
Broadcasting is a very useful feature of NumPy that will let arrays with differing shapes still be used together. In most cases, broadcasting is faster, and it is more memory efficient than the equivalent full array operation.
print "Shape of X:", x.shape
print "Shape of Y:", y.shape
Now, here are three identical assignments. The first one takes full advantage of broadcasting by allowing NumPy to automatically add a new dimension to the left. The second explicitly adds that dimension with the special NumPy alias "np.newaxis". These first two creates a singleton dimension without any new arrays being created. That singleton dimension is then implicitly tiled, much like the third example to match with the RHS of the addition operator. However, unlike the third example, the broadcasting merely re-uses the existing data in memory.
a = x + y
print a.shape
b = x[np.newaxis, :, :] + y
print b.shape
c = np.tile(x, (4, 1, 1)) + y
print c.shape
print "Are a and b identical?", np.all(a == b)
print "Are a and c identical?", np.all(a == c)
Another example of broadcasting two 1-D arrays to make a 2-D array.
x = np.arange(-5, 5, 0.1)
y = np.arange(-8, 8, 0.25)
print x.shape, y.shape
z = x[np.newaxis, :] * y[:, np.newaxis]
print z.shape
# More concisely
y, x = np.ogrid[-8:8:0.25, -5:5:0.1]
print x.shape, y.shape
z = x * y
print z.shape