#### Indexing and slicing

### Basic Indexing

Basic Indexing can be done to access a particular element from the `NumPy`

arrays.

#### 1. One-dimensional array

**Creating a one-dimensional array**

import numpy as np one_d=np.array([10,20,30,40]) print (one_d) #Output:array([10, 20, 30, 40])

**Accessing elements from the array by positive indexing**

In Python, all indices are zero_based. Index 0 represents the first element in the array.

`one_d[2]`

→ 30

**Accessing elements from the array by negative indexing**

Negative indexing starts from the end of the array. `-1`

represents the last element.

`one_d[-1]`

→ 40

#### 2. Two-dimensional array

**Creating a two-dimensional array**

two_d=np.array([[0,1],[2,3],[4,5]]) print (two_d)#Output:[[0 1] [2 3] [4 5]]

**Accessing particular element in a two-dimensional array**

x[i,j] or x[(i,j)]

i → row_index (it starts from 0)

j → column_index (it starts from 0)

print (two_d[(1,2)])#Output: 5print (two_d[1,2])#Output: 5

**Accessing a particular row in a two-dimensional array**

If we provide a single index, it will be taken as row_index

`x[i]`

i → row_index

print (two_d[(1)])#Output:[3 4 5]

**Accessing a particular column in a two-dimensional array**

`x[:,j]`

: → **i (row_index)**, take all values (**:** is a full slice, from start to end)

j → column_index

print (two_d[:,1])#Output:[1 4 7]

#### 3. Three-dimensional array

**Creating a three-dimensional array**

three_d=np.array([[[0,1],[2,3]],[[4,5],[6,7]]]) print (three_d)#Output:[[[0 1] [2 3]] [[4 5] [6 7]]]

**Accessing a particular element in a three-dimensional array**

print (three_d[1,0,1])#Output: 5print (three_d[(1,0,1)])#Output: 5print (three_d[(-1,-1,-1)])#Output: 7

**Accessing particular element from a three-dimensional array using negative indexing**

print (three_d[(-1,-1,-1)])#Output: 7

**Accessing a particular matrix (or two-dimensional array) in a three-dimensional array**

x[1] → selects the first matrix.

If we specify only the first index, it will select the particular matrix.

print (three_d[(1)])#Output:[[4 5] [6 7]]

**Accessing a particular row in a particular matrix**

`x[i,j]`

→ If we specify only i and j values, it will select the row(j) from the matrix(i)

print (three_d[(1,0)])#Output:[4 5]

**Accessing a particular column in a particular matrix**

`x[i,:,k]`

→ select **column k** from** matrix i**.

**j** is given as` :`

which means full slice.[All rows)

print (three_d[1,:,1])#Output:[5 7]

**Accessing the elements at the same position from each matrix.**

`x[:,j,k]`

→ It will select the element at **row j** and **column k** in all the matrix.

**i **is given as` :`

which means full slice.[ all matrix]

print (three_d[:,1,1])#Output:[3 7]

#### IndexError

Attempting to use an index that is too large will result in an IndexError.

**Example 1: One-dimensional array**

print (one_d[5])#Output:IndexError: index 5 is out of bounds for axis 0 with size 4

### Basic Slicing

Basic slicing extends Python’s basic concept of slicing to N dimensions.

**1. Slicing one-dimensional array**

In Slicing, we can specify a range of index

`s[i:j:k] — slice of `

*s* from *i* to *j* with step *k*

i →start index

j → stop index

k → step (k should not be 0)

slice1=one_d[0:3:2] print (slice1) #Output: [10, 30]

It will slice elements from 0 indexes to the third index(exclusive) by step 2.

The return type of basic slicing will be `ndarray`

print (type(slice1))#Output:numpy.ndarray

All arrays generated by basic slicing are always “views” of the original array.

**Views:** An array that does not own its data, but refers to another array’s data instead.

So if we modify the original array, the view also modified. Similarly, if we modify the view, the original array also modified.

**Example 1: Modifying slice1 will also modify the original array ****one_d**

slice1[0]=99999#Modifying slice1 will modify the original array also.print (slice1)#Output:[99999, 30]print(one_d)#Output:[99999, 20, 30, 40]

**Example 2: Modifying the original array will also modify the array generated by basic slicing**

one_d[0]=77777 print (one_d)#Output:[77777 20 30 40]print (slice1)#Output: [77777 30]

**Note: **`NumPy`

slicing creates a view instead of a copy as in the case of builtin Python sequences such as string, tuple, and list. Care must be taken when extracting a small portion from a large array which becomes useless after the extraction because the small portion extracted contains a reference to the larger original array whose memory will not be released until all arrays derived from it are garbage-collected. In such cases, an explicit `copy()`

is recommended. –Python docs

**Example 3: Omitted start and stop index defaults to the first index and last index of the array. The negative step indicates the reverse direction.**

print (one_d[::-2])#Output:array([40, 20])

#### 2. Slicing two-dimensional array

By Slicing a two-dimensional array in both axis, we can get a subset of the original array.

`x[i:j:k,l:m:n]`

i:j:k → Slice along the x-axis (rows)

l:m:n → slice along y-axis(columns)

**Example 1:
**

`two_d[1:,1:]`

→Select elements from row 1 to the last row and column 1 to the last column.print (two_d[1:,1:])#Output:[[4 5] [7 8]]

**Example 2:
**

`two_d[0:2,1:]`

→ Select elements from row 0 to row2(excluded) and column 1 till the last column.0:2 → Slice for x-axis → select row 0 till row 2(excluded)

1: → Slice for y-axis → select column 1 till the last column

print (two_d[0:2,1:])#Output:[[1 2] [4 5]]

**Example 3:
**

**two_d[1:,::2]**

`1:`

→Select row 1 till the last row

`::2`

→ Select columns from columns1 to the last column by step 2

print (two_d[1:,::2])#Output:[[3 5] [6 8]]

#### 3. Slicing three-dimensional array

By slicing three-dimensional array along three axes, we can select a subset of the original array

`x[a:b:c,i:j:k,l:m:n]`

a:b:c →Slice the plane

i:j:k → Slice the rows

l:m:n → Slice the columns

**Example 1:
**

`three_d[:,:,1:] `

: → Select all planes

: → Select all rows

1: → Select columns from column 1 to the last column

print (three_d[:,:,1:])#Output:[[[1] [3]] [[5] [7]]]

#### Out of Range indexes

Out of range indexes are handled gracefully by slicing.

print (three_d[2:,:,:])#Output: []

### Advanced Indexing

#### Integer Array Indexing

Integer array indexing allows the selection of arbitrary items in the array based on their *N*-dimensional index. Each integer array represents a number of indexes into that dimension- Python docs

**Example 1: Two_dimensional array**

`two_d[[0,1,2],[0,1,2]]`

For each row, a specific element to be selected.

row_index → [0,1,2] → row index specifies row to be selected

column_index →[0,1,2] → column index specifies the element to choose for the corresponding row

print (two_d[[0,1,2],[0,1,2]])#Output:[0 4 8]

**Example 2: Three-dimensional array**

`three_d[[0,1],[0,1],[0,1]]`

Result will be it will select elements from ( plane 0,row 0,col 0) and (plane 1,row1,col1).

print (three_d[[0,1],[0,1],[0,1]])#Output:[0 4 8]

### Git Hub Link

The code used here is available as Jupyter Notebook on Git Hub

### Conclusion

- In basic indexing, out of range indexes will raise an
**IndexError** - In basic slicing, out of range indexes are handled gracefully.
- All arrays generated by basic slicing are the
**views**of the original array. - In basic indexing,
**x[i,j,k]**is equivalent to**x[(i,j,k)]** - In basic slicing, we should not use a tuple of slice objects.

a[1:,1:] → right

a[(1:,1:)] → wrong **Full slice**will select the entire plane/rows/columns based on the axes mentioned.

a[:] → It will select**all rows**in a one-dimensional array

a[1,:] →It will select**all columns**in row1 in a two-dimensional array

a[:,1,1] →It will select row 1 and col1 in**all planes**in a three-dimensional array- For the trailing index, the omitted index represents a full slice

a[1] is the same as a[1,:] in a two-dimensional array

a[1,1] is same as a[1,1,:] in three-dimensional array