# Working with Ndarrays

Numpy arrays are easy to use and have many properties and built-in functions that make them a good choice for many applications, especially but not exclusively working with numerical data.

## Array Elements and Slices

Each element can be addressed by its index or indices. As for other ordered sequences, numbering starts from zero. Indices are enclosed in square brackets. The dimensions are usually enclosed in a single set of square brackets.

A[i,j,k]


Negative indices count from the last element.

V[-1]   #last element
A[0,-2] #first in column 0, next to last in column 1.


### Slicing Arrays

Subarrays, or slices, are indicated by the colon-separated range operator we have seen several times now. As usual for Python, the upper bound must be one greater than the intended upper bound, i.e. it is non-inclusive. We can omit lower and upper bounds if they are the edges; [lb:] extends from lb to the last element, while [:ub] extends from the beginning to ub-1. The entire axis is expressed as [:].

import numpy
A=numpy.zeros((100,100))
B=A[0:11,:]
C=A[S1:E1,S2:E2]
D=A[:,1]  #second column


Pay close attention to negative indices, especially when they are part of a slice specification.

V=np.array([0,1,2,3,4])
u=np.arange(25).reshape(5,5)
V[-1]
4
V[:-1] #note element versus slice
[0,1,2,3]
u[:-1,:]
[[ 0  1  2  3  4]
[ 5  6  7  8  9]
[10 11 12 13 14]
[15 16 17 18 19]]


An Ndarray can take as its index an integer or Boolean array.

A=np.array([-2.,3.,-8.,-11.,12.,12.,45.,19.])
I=np.array([2,4,5])
valid=A>0
print(valid)
[False  True False False  True  True  True  True]
print(A[I])
[-8.,12.,12.]
print(A[valid])
[  3.  12.  12.  45.  19.]


## Axes

NumPy refers to dimensions as axes. Many NumPy functions take an optional axis argument. As always, we number axes from zero.

a=np.arange(12).reshape(3,4)
print(a)
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]
print(a.sum())
66
print(a.sum(0))  # across rows for each column
[12 15 18 21]
print(a.sum(1))  # across columns for each row
[ 6 22 38]


In sum and similar methods, such as prod (product), the axis argument is the one to be summed out, that is, eliminated. In the above examples, the first sum uses all elements, resulting in a single value. In the examples with an optional axis argument, we reduce the rank by one and the shape of the result removes the summed axis. Starting from a rank-2, $3 \times 4$ array, the sum over axis 0 produces a 4-element rank-1 array. The sum over axis 1 results in a 3-element rank-1 array.

## Array Operations

NumPy provides many functions, including a large selection of mathematical functions, that accept array arguments as well as scalars. They operate on the arrays elementwise. The arithmetic operators are also defined to work elementwise on arrays; this is called operator overloading since these operators can work either on ordinary scalar numerical variables or on Ndarrays.

T=numpy.ones(4)
Z=3.0*T+numpy.ones_like(T)
I=numpy.array([1,0,0,0])
A=math.pi*I
B=numpy.sin(A)
C=A/B  #remember: elementwise


Array operations and NumPy built-in functions can be many times faster than loops, so they should be utilized whenever possible.

Exercise

Generate an NxM two-dimensional array A with the smallest element 1 and the largest one N*M*incr. Make sure your values are inclusive and the size of the array is correct. Use reshape to convert from the one-d arange to the NxM array. N, M, and incr should be variables.

Create another array B the same shape, such that it is 0.25*A+.01.

Create a third array C that is the elementwise sum of A and B.

Create a fourth array D that sums C over the second axis. Print the shape, size, and the values of D.

Print the first N-2 rows and M-3 columns of B. Be sure B is large enough. Use the shape of B to check that this is true.

Example solution

import numpy as np

N=4
M=5

incr=0.01

A=incr*np.arange(1.,N*M+1).reshape(N,M)

B=0.25*A+.01

C=A+B

D=sum(C,1)

if B.shape[0]>1 and B.shape[1]>4:
print(B[:N-1,:M-4])
else:
print("B is too small.")



Previous
Next