# numpy array split and search

## Splitting NumPy Arrays

Splitting is reverse operation of Joining.

Joining merges multiple arrays into one and Splitting breaks one array into multiple.

We use `array_split()`

for splitting arrays, we pass it the array we want to split and the number of splits.

### Example

Split the array in 3 parts:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 3)
print(newarr)

If the array has less elements than required, it will adjust from the end accordingly.

### Example

Split the array in 4 parts:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 4)
print(newarr)

## Split Into Arrays

The return value of the `array_split()`

method is an array containing each of the split as an array.

If you split an array into 3 arrays, you can access them from the result just like any array element:

### Example

Access the splitted arrays:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 3)
print(newarr[0])
print(newarr[1])
print(newarr[2])

## Splitting 2-D Arrays

Use the same syntax when splitting 2-D arrays.

Use the `array_split()`

method, pass in the array you want to split and the number of splits you want to do.

### Example

Split the 2-D array into three 2-D arrays.

` ````
```import numpy as np
arr = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
newarr = np.array_split(arr, 3)
print(newarr)

The example above returns three 2-D arrays.

Let’s look at another example, this time each element in the 2-D arrays contains 3 elements.

### Example

Split the 2-D array into three 2-D arrays.

` ````
```import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
newarr = np.array_split(arr, 3)
print(newarr)

The example above returns three 2-D arrays.

In addition, you can specify which axis you want to do the split around.

The example below also returns three 2-D arrays, but they are split along the row (axis=1).

### Example

Split the 2-D array into three 2-D arrays along rows.

` ````
```import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
newarr = np.array_split(arr, 3, axis=1)
print(newarr)

An alternate solution is using `hsplit()`

opposite of `hstack()`

### Example

Use the `hsplit()`

method to split the 2-D array into three 2-D arrays along rows.

` ````
```import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
newarr = np.hsplit(arr, 3)
print(newarr)

## Searching Arrays

You can search an array for a certain value, and return the indexes that get a match.

To search an array, use the `where()`

method.

### Example

Find the indexes where the value is 4:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 4, 4])
x = np.where(arr == 4)
print(x)

The example above will return a tuple: `(array([3, 5, 6],)`

Which means that the value 4 is present at index 3, 5, and 6.

### Example

Find the indexes where the values are even:

` `

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
x = np.where(arr%2 == 0)
print(x)

### Example

Find the indexes where the values are odd:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
x = np.where(arr%2 == 1)
print(x)

## Search Sorted

There is a method called `searchsorted()`

which performs a binary search in the array, and returns the index where the specified value would be inserted to maintain the search order.

The `searchsorted()`

method is assumed to be used on sorted arrays.

### Example

Find the indexes where the value 7 should be inserted:

` ````
```import numpy as np
arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7)
print(x)

Example explained: The number 7 should be inserted on index 1 to remain the sort order.

The method starts the search from the left and returns the first index where the number 7 is no longer larger than the next value.

## Search From the Right Side

By default the left most index is returned, but we can give `side='right'`

to return the right most index instead.

### Example

Find the indexes where the value 7 should be inserted, starting from the right:

` ````
```import numpy as np
arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7)
print(x)

Example explained: The number 7 should be inserted on index 2 to remain the sort order.

The method starts the search from the right and returns the first index where the number 7 is no longer less than the next value.

## Multiple Values

To search for more than one value, use an array with the specified values.

### Example

Find the indexes where the values 2, 4, and 6 should be inserted:

` ````
```import numpy as np
arr = np.array([1, 3, 5, 7])
x = np.searchsorted(arr, [2, 4, 6])
print(x)

The return value is an array: `[1 2 3]`

containing the three indexes where 2, 4, 6 would be inserted in the original array to maintain the order.

## Filtering Arrays

Getting some elements out of an existing array and creating a new array out of them is called *filtering*.

In NumPy, you filter an array using a *boolean index list*.

A *boolean index list* is a list of booleans corresponding to indexes in the array.

If the value at an index is `True`

that element is contained in the filtered array, if the value at that index is `False`

that element is excluded from the filtered array.

### Example

Create an array from the elements on index 0 and 2:

` ````
```import numpy as np
arr = np.array([41, 42, 43, 44])
x = [True, False, True, False]
newarr = arr[x]
print(newarr)

The example above will return `[41, 43]`

, why?

Because the new filter contains only the values where the filter array had the value `True`

, in this case, index 0 and 2.

## Creating the Filter Array

In the example above we hard-coded the `True`

and `False`

values, but the common use is to create a filter array based on conditions.

### Example

Create a filter array that will return only values higher than 42:

` ````
```import numpy as np
arr = np.array([41, 42, 43, 44])
# Create an empty list
filter_arr = []
# go through each element in arr
for element in arr:
# if the element is higher than 42, set the value to True, otherwise False:
if element > 42:
filter_arr.append(True)
else:
filter_arr.append(False)
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)

### Example

Create a filter array that will return only even elements from the original array:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
# Create an empty list
filter_arr = []
# go through each element in arr
for element in arr:
# if the element is completely divisble by 2, set the value to True, otherwise False
if element % 2 == 0:
filter_arr.append(True)
else:
filter_arr.append(False)
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)

## Creating Filter Directly From Array

The above example is quite a common task in NumPy and NumPy provides a nice way to tackle it.

We can directly substitute the array instead of the iterable variable in our condition and it will work just as we expect it to.

### Example

Create a filter array that will return only values higher than 42:

` ````
```import numpy as np
arr = np.array([41, 42, 43, 44])
filter_arr = arr > 42
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)

### Example

Create a filter array that will return only even elements from the original array:

` ````
```import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
filter_arr = arr % 2 == 0
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)