# Indexing and Slicing

## 1-D array

1-D NumPy Array elements can be accessed by index, using syntax identical to Python lists: `array[index]` for a single element, or `array[start:end]` for a slice, where `start` and `end` are the starting and ending indexes for the slice.

```python
arr = np.arange(10)

arr
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr[5]
# 5

arr[-1]
# 9

arr[5:8]
# array([5, 6, 7])

arr[:3]
# array([0, 1, 2])

arr[-3:]
# array([7, 8, 9])

# ndarray slicing is shallow copy
arr[5:8] = 12
arr
# array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])

# assign new variable to ndarray slicing is still 
# shallow copy
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])
```

Notice that when we select multiple elements, we get an array.

## 2-D Array

Nested Arrays can be accessed by adding additional comma-separated parameters.

```python
arr2d = np.array([[1, 2, 3], 
                  [4, 5, 6], 
                  [7, 8, 9]])
arr2d[2]
# array([7, 8, 9])

arr2d[0, 2]
# 3

arr2d[:2, 1:]
# array([[2, 3],[5, 6]])

arr2d[1, :2]
# array([4, 5])

arr2d[:, :1]
# array([[1],[4],[7]])
```

![](/files/-M2dsXqnwGKoRLH5p8x7)

Note that when we work with arrays that have more than one dimension, the relationship between the interior arrays is defined in terms of *axes*. A two-dimensional array has two axes: axis 0 represents the values that share the same indexical position (are in the same column), and axis 1 represents the values that share an array (are in the same row). This is illustrated below.

![Diagram showing the axes in an array](https://s3.amazonaws.com/codecademy-content/courses/numpy/NumPy+Array+fixed.svg)

## Boolean Indexing

NumPy elements can be indexed using conditionals. The syntax to filter an array using a conditional is `array_name[conditional]`.

The returned array will contain only the elements for which the conditional evaluates to `True`.

```python
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 
                  'Will', 'Joe', 'Joe'])
data = randn(7, 4)
names
# array(['Bob', 'Joe', 'Will', 'Bob', 
#        'Will', 'Joe', 'Joe'], dtype='|S4')
data
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [ 2.1452, 0.8799, -0.0523, 0.0672],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

names == 'Bob'
# array([True, False, False, True, 
#        False, False, False], dtype=bool)

data[names == 'Bob']
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [2.1452, 0.8799, -0.0523, 0.0672]])

data[names == 'Bob', 2:]
# array([[-0.2349, 1.2792],
#        [-0.0523, 0.0672]])

data[names == 'Bob', 3]
# array([ 1.2792, 0.0672])

data[-(names == 'Bob')]
# array([[-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

data[names != 'Bob']
# array([[-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

# use & (and) and | (or) for more than one comparision
data[(names == 'Bob') | (names == 'Will')]
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [ 2.1452, 0.8799, -0.0523, 0.0672],
#        [-1.0023, -0.1698, 1.1503, 1.7289]])
```

## Fancy Indexing

Fancy indexing is a term adopted by NumPy to describe indexing using integer arrays. Passing multiple index arrays does something slightly different; it selects a 1D array of elements corresponding to each tuple of indices:

```python
arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i
arr
# array([[ 0., 0., 0., 0.],
#        [ 1., 1., 1., 1.],
#        [ 2., 2., 2., 2.],
#        [ 3., 3., 3., 3.],
#        [ 4., 4., 4., 4.],
#        [ 5., 5., 5., 5.],
#        [ 6., 6., 6., 6.],
#        [ 7., 7., 7., 7.]])

arr[[4, 3, 0, 6]]
# array([[ 4., 4., 4., 4.],
#        [ 3., 3., 3., 3.],
#        [ 0., 0., 0., 0.],
#        [ 6., 6., 6., 6.]])

# Using negative indices select rows from the end
arr[[-3, -5, -7]]
# array([[ 5., 5., 5., 5.],
#        [ 3., 3., 3., 3.],
#        [ 1., 1., 1., 1.]])

# create 1-dimension then reshape
arr = np.arange(32).reshape((8, 4))
# array([[ 0, 1, 2, 3],
#        [ 4, 5, 6, 7],
#        [ 8, 9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19],
#        [20, 21, 22, 23],
#        [24, 25, 26, 27],
#        [28, 29, 30, 31]])

arr[[1, 5, 7, 2], [0, 3, 1, 2]]
# array([ 4, 23, 29, 10])

arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
# array([[ 4, 7, 5, 6],
# [20, 23, 21, 22],
# [28, 31, 29, 30],
# [ 8, 11, 9, 10]])

arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]
# array([[ 4, 7, 5, 6],
# [20, 23, 21, 22],
# [28, 31, 29, 30],
# [ 8, 11, 9, 10]])
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lei-d.gitbook.io/python-for-data-analysis/numpy-1/indexing-and-slicing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
