Advanced indexing is triggered when the selection object, obj, is a non-tuple sequence object, an ndarray (of data type integer or bool), or a tuple with at least one sequence object or ndarray (of data type integer or bool). Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view). There are two types of advanced indexing: integer and Boolean.

## Integer Array Indexing

Integer array indexing allows selection of arbitrary items in the array based on their N-dimensional index. Each integer array represents a number of indexes into that dimension. When the index consists of as many integer arrays as the array being indexed has dimensions, the indexing is straight forward.

### Example 1:

In the example below, from each row, a specific element is selected. The row index is [0, 1, 2] and the column index is [0, 1, 0]. Using both indices the elements are selected from the given array. The selection includes elements at (0,0), (1,1) and (2,0) from the array.

```import numpy as np

#creating array
x = np.array([[1, 2], [3, 4], [5, 6]])

#to slice the array
y = x[[0, 1, 2], [0, 1, 0]]

#printing arrays
print("x contains:")
print(x)
print("\ny contains:")
print(y)
```

The output of the above code will be:

```x contains:
[[1 2]
[3 4]
[5 6]]

y contains:
[1 4 5]
```

### Example 2:

In the example below, elements placed at corners of a 4x3 array are selected. To use advanced indexing one needs to select all elements explicitly. Therefore, the row indices of selection will be [0, 0] and [3,3] whereas the column indices will be [0,2] and [0,2].

```import numpy as np

#creating array
x = np.array([[ 0,  1,  2],
[ 3,  4,  5],
[ 6,  7,  8],
[ 9, 10, 11]])

#to slice the array
rows = np.array([[0, 0], [3, 3]])
columns = np.array([[0, 2], [0, 2]])
y = x[rows, columns]

print("x contains:")
print(x)
print("\ny contains:")
print(y)
```

The output of the above code will be:

```x contains:
[[ 0  1  2]
[ 3  4  5]
[ 6  7  8]
[ 9 10 11]]

y contains:
[[ 0  2]
[ 9 11]]
```

Advanced and basic indexing can be combined by using slice :, ellipsis ... or numpy.newaxis in the index array.

### Example 3:

In the example below, slice is used for row and advanced index for column. The result is the same when slice is used for both. But advanced index results in copy and may have different memory layout.

```import numpy as np

#creating array
x = np.array([[ 0,  1,  2],
[ 3,  4,  5],
[ 6,  7,  8],
[ 9, 10, 11]])

#using slice is used for row and
y = x[1:4, [1,2]]

#using slice at both places
z = x[1:4, 1:3]

print("x contains:")
print(x)
print("\ny contains:")
print(y)
print("\nz contains:")
print(z)
```

The output of the above code will be:

```x contains:
[[ 0  1  2]
[ 3  4  5]
[ 6  7  8]
[ 9 10 11]]

y contains:
[[ 4  5]
[ 7  8]
[10 11]]

z contains:
[[ 4  5]
[ 7  8]
[10 11]]
```

## Boolean Array Indexing

This advanced indexing is used when the resultant object is meant to be the result of Boolean operations like comparison operators.

### Example 1:

In the example below, elements which are greater than 25 are returned as a result of boolean array indexing.

```import numpy as np

#creating array
x = np.array([[10, 15, 20],
[25, 30, 35],
[40, 45, 50]])

#technique to slice the array
y = x[x > 25]

#printing arrays
print("x contains:")
print(x)
print("\ny contains:")
print(y)
```

The output of the above code will be:

```x contains:
[[10 15 20]
[25 30 35]
[40 45 50]]

y contains:
[30 35 40 45 50]
```

### Example 2:

Similarly, this technique can be used to delete all NaN (Not a Number) from the array. Consider the example below:

```import numpy as np

#creating array
x = np.array([[10, 15, np.nan],
[np.nan, 30, 35],
[40, np.nan, 50]])

#technique to slice the array
y = x[~np.isnan(x)]

#printing arrays
print("x contains:")
print(x)
print("\ny contains:")
print(y)
```

The output of the above code will be:

```x contains:
[[10. 15. nan]
[nan 30. 35.]
[40. nan 50.]]

y contains:
[10. 15. 30. 35. 40. 50.]
```

### Example 3:

In the same way, it can be used to filter out the non-complex numbers from the array. Consider the example below:

```import numpy as np

#creating array
x = np.array([[10, 15+1j, 20],
[25+2j, 30, 35],
[40, 45, 50+3j]])

#technique to slice the array
y = x[np.iscomplex(x)]

#printing array
print("y contains:")
print(y)
```

The output of the above code will be:

```y contains:
[15.+1.j 25.+2.j 50.+3.j]
```

5