# Indexing, Masks, Views and Copies — NumPy / Pandas / scikit-learn

Source: https://www.skillbyai.com/en/numpy-pandas-sklearn/a-index

> Selecting data safely.

## Slices, boolean masks, fancy indexing

Slicing (`a[1:4]`, `a[::3]`) returns a **view** that shares memory with the original, so writing to it changes the source. **Boolean masks** (`a[a > 50]`) and **fancy indexing** with lists of positions (`a[[0, 2, 4]]`) return **copies**. Multi-dimensional arrays take one index per axis (`m[1, 2]`, `m[:, 0]`). Use `.copy()` explicitly when you need independent data.

## Selecting and the view versus copy rule, run

I ran this with Python 3.12.3 and NumPy 2.5.3. Writing -1 through a slice changes the original array; writing 999 into the result of fancy indexing does not.

```python
import numpy as np

a = np.arange(10, 100, 10)
print(a)
print(a[2], a[-1], a[1:4], a[::3])
mask = a > 50
print(mask)
print(a[mask])
print(a[[0, 2, 4]])                        # fancy indexing

m = np.arange(12).reshape(3, 4)
print(m[1, 2], m[:, 0], m[m % 2 == 0])

view = a[1:4]
view[0] = -1                               # slices are views
print(a[:4])
copy = a[[1, 2, 3]]
copy[0] = 999                              # fancy indexing returns a copy
print(a[:4])
```

Output:

```
[10 20 30 40 50 60 70 80 90]
30 90 [20 30 40] [10 40 70]
[False False False False False  True  True  True  True]
[60 70 80 90]
[10 30 50]
6 [0 4 8] [ 0  2  4  6  8 10]
[10 -1 30 40]
[10 -1 30 40]
```

## Masks replace if statements

Filtering with a boolean mask is the vectorised version of a loop with an if statement, and is much faster.

**Quiz:** Which operation returns a view sharing memory with the original?

- [ ] np.copy(a)
- [ ] A boolean mask
- [ ] Fancy indexing with a list
- [x] A basic slice such as a[1:4]

*Answer:* A basic slice such as a[1:4]. Slices are views; masks and lists copy.
