NumPy

Array Fundamentals

Indexing NumPy arrays: positions, slices, lists of positions, boolean masks, new axes and ellipses.

The array we will index


        import numpy as np
        one = np.array([10, 20, 30, 40, 50, 60, 70, 80])
      

Basic indexing


          one[2]
          # ans: 30
          one[-1]
          # ans: 80
        

One integer picks one element, counting from 0, or from -1 at the end, exactly like a list.

Slicing


          # start 1, stop before 6, step 2
          one[1:6:2]
          # ans: array([20, 40, 60])
        

A slice of an array is a view: it shares memory with one, so changing it changes one.

Fancy indexing


          # a list of positions, in any order, repeats allowed
          one[[4, 0, 3, 0]]
          # ans: array([50, 10, 40, 10])
        

The small numbers show the order of the result: position 0 is used twice. Fancy indexing returns a copy.

Masking


          one[(one < 30) & (one > 60)]
          # ans: array([], dtype=int64): nothing is both below 30 and above 60
          one[(one < 30) | (one > 60)]
          # ans: array([10, 20, 70, 80])
        
one
one < 30
one > 60
&

A comparison gives one True/False per element; & (and) / | (or) combine them, and the array keeps the True positions.

newaxis / None indexing


          one.shape
          # ans: (8,)
          one[:, np.newaxis]
          # ans: shape (8, 1): a column
          one[:, None]
          # ans: the same: None is np.newaxis
        

shape (8,)

Higher dimensions and the ellipsis


          two = np.arange(27).reshape(3, 3, 3)
          two[1, ...]
          # ans: array([[ 9, 10, 11], [12, 13, 14], [15, 16, 17]])
        

... means "all the remaining axes", so two[1, ...] is two[1, :, :]: the middle 3×3 block.

Remember

Integers and slices

a[2], a[1:6:2]: like lists, but slices are views.

Lists of positions

a[[4, 0, 3]] picks in that order, as a copy.

Masks

a[(a > x) & (a < y)]: brackets around each comparison.

Shape tools

None adds an axis; ... fills in the rest.