# 3.6. Array Select¶

## 3.6.1. Unique¶

import numpy as np

a = np.array([[1, 2, 3, 1],
[1, 4, 5, 6]])

np.unique(a)
# array([1, 2, 3, 4, 5, 6])

np.unique(a, axis=0)
# array([[1, 2, 3, 1],
#        [1, 4, 5, 6]])

np.unique(a, axis=1)
# array([[1, 1, 2, 3],
#        [1, 6, 4, 5]])


## 3.6.2. Diagonal¶

import numpy as np

a = np.array([[1, 2],
[3, 4]])

a.diagonal()
# array([1, 4])

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6]])

a.diagonal()
# array([1, 5])

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

a.diagonal()
# array([1, 5, 9])


## 3.6.3. Nonzero¶

• Each element of the tuple contains one of the indices for each nonzero value.

• Therefore, the length of each tuple element is the number of nonzeros in the array.

• The first element of the tuple is the first index for each of the nonzero values: ([0, 0, 1, 1]).

• The second element of the tuple is the second index for each of the nonzero values: ([0, 2, 0, 2]).

• Pairs are zipped (first and second tuple):

• 0, 0

• 0, 2

• 1, 0

• 1, 2

import numpy as np

a = np.array([[1, 0, 2],
[3, 0, 4]])

a.nonzero()
# (array([0, 0, 1, 1]),
#  array([0, 2, 0, 2]))

a[a.nonzero()]
# array([1, 2, 3, 4])


## 3.6.5. Single argument¶

• where(boolarray)

• indexes of elements

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6])

np.where(a != 2)
# (array([0, 2, 3, 4, 5]),)

np.where(a % 2 == 0)
# (array([1, 3, 5]),)

np.where( (a>2) & (a<5) )
# (array([2, 3]),)

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

np.where(a % 2 == 0)
# (array([0, 0, 1]),
#  array([0, 2, 1]))

np.where( (a>2) & (a<5) )
# (array([0, 1]),
#  array([2, 0]))


## 3.6.6. Multiple argument¶

• where(boolarray, truearray, falsearray):

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

np.where(a < 5, 'small', 'large')
# array([['small', 'small', 'small'],
#        ['small', 'large', 'large'],
#        ['large', 'large', 'large']], dtype='<U5')

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

np.where(a % 2 == 0, 'even', 'odd')
# array([['odd', 'even', 'odd'],
#        ['even', 'odd', 'even'],
#        ['odd', 'even', 'odd']], dtype='<U4')

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

np.where(a % 2 == 0, np.nan, a)
# array([[ 1., nan,  3.],
#        [nan,  5., nan],
#        [ 7., nan,  9.]])


## 3.6.7. Take¶

import numpy as np

a = np.array([1, 2, 3])
at_index = np.array([0, 0, 1, 2, 2, 1])

a.take(at_index)
# array([1, 1, 2, 3, 3, 2])

import numpy as np

a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

at_index = np.array([0, 0, 1])

a.take(at_index, axis=0)
# array([[1, 2, 3],
#        [1, 2, 3],
#        [4, 5, 6]])

a.take(at_index, axis=1)
# array([[1, 1, 2],
#        [4, 4, 5],
#        [7, 7, 8]])


## 3.6.8. Assignments¶

"""
* Assignment: Numpy Select Isin
* Complexity: easy
* Lines of code: 6 lines
* Time: 5 min

English:
1. Set random seed to 0
2. Generate a: np.ndarray of size 50x50
3. a must contains random integers from 0 to 1024 inclusive
4. Create result: np.ndarray with elements selected from a which are power of two
5. Sort result in descending order
6. Run doctests - all must succeed

Polish:
1. Ustaw ziarno losowości na 0
2. Wygeneruj a: np.ndarray rozmiaru 50x50
3. a musi zawierać losowe liczby całkowite z zakresu od 0 do 1024 włącznie
4. Stwórz result: np.ndarray z elementami wybranymi z a, które są potęgami dwójki
5. Posortuj result w kolejności malejącej
6. Uruchom doctesty - wszystkie muszą się powieść

Hints:
* np.isin(a, b)
* np.flip(a)

Tests:
>>> import sys; sys.tracebacklimit = 0

>>> type(result) is np.ndarray
True
>>> result
array([1024, 1024, 1024, 1024, 1024, 1024,  512,  512,  512,  512,  256,
256,  256,  256,  256,  128,  128,  128,  128,  128,   64,   32,
32,   32,   32,   32,   16,   16,   16,   16,   16,   16,    8,
8,    4,    2,    2,    2,    2,    2])
"""

import numpy as np
np.random.seed(0)

result = ...