Fancy indexing and index tricks¶
Indexing with Arrays of Indices¶
>>> a = np.arange(12)**2 # the first 12 square numbers
>>> i = np.array( [ 1,1,3,8,5 ] ) # an array of indices
>>> a[i] # the elements of a at the positions i
array([ 1, 1, 9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] ) # a bidimensional array of indices
>>> a[j] # the same shape as j
array([[ 9, 16],
[81, 49]])
>>> let a = build 12 (^2) :: Vector Z
>>> let i = fromList [1,1,3,8,5] :: Vector I
>>> flatten ((asRow a) ?? (All, Pos i))
[1,1,9,64,25]
>>> let j = fromLists [[3,4],[9,7]] :: Matrix I
>>> remap (asRow (scalar 0)) (j) ((fromRows . replicate (rows j)) a)
(2><2)
[ 9, 16
, 81, 49 ]
>>> palette = np.array( [ [0,0,0], # black
... [255,0,0], # red
... [0,255,0], # green
... [0,0,255], # blue
... [255,255,255] ] ) # white
>>> image = np.array( [ [ 0, 1, 2, 0 ], # each value corresponds to a color in the palette
... [ 0, 3, 4, 0 ] ] )
>>> palette[image] # the (2,4,3) color image
array([[[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0]],
[[ 0, 0, 0],
[ 0, 0, 255],
[255, 255, 255],
[ 0, 0, 0]]])
>>> let palette = fromLists [[0,0,0],[255,0,0],[0,255,0],[0,0,255],[255,255,255]] :: Matrix I
>>> let image = fromLists [[0,1,2,0],[0,3,4,0]] :: Matrix I
>>> fmap (\img -> palette ?? (Pos img, All)) (toRows image) -- almost 3D, [Matrix Z] instead
[(4><3)
[ 0, 0, 0
, 255, 0, 0
, 0, 255, 0
, 0, 0, 0 ],(4><3)
[ 0, 0, 0
, 0, 0, 255
, 255, 255, 255
, 0, 0, 0 ]]
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> i = np.array( [ [0,1], # indices for the first dim of a
... [1,2] ] )
>>> j = np.array( [ [2,1], # indices for the second dim
... [3,3] ] )
>>>
>>> a[i,j] # i and j must have equal shape
array([[ 2, 5],
[ 7, 11]])
>>>
>>> a[i,2]
array([[ 2, 6],
[ 6, 10]])
>>>
>>> a[:,j] # i.e., a[ : , j]
array([[[ 2, 1],
[ 3, 3]],
[[ 6, 5],
[ 7, 7]],
[[10, 9],
[11, 11]]])
>>> let a = (3><4) [0::Z ..]
>>> let i = fromLists [[0,1],[1,2]] :: Matrix I
>>> let j = fromLists [[2,1],[3,3]] :: Matrix I
>>> remap i j a
(2><2)
[ 2, 5
, 7, 11 ]
>>> remap i (asColumn (scalar 2)) a
(2><2)
[ 2, 6
, 6, 10 ]
>>> fmap (\r -> remap (asRow (scalar r)) j a) (toList ((rows a) |> [0..])) -- emulating 3D
[(2><2)
[ 2, 1
, 3, 3 ],(2><2)
[ 6, 5
, 7, 7 ],(2><2)
[ 10, 9
, 11, 11 ]]
>>> time = np.linspace(20, 145, 5) # time scale
>>> data = np.sin(np.arange(20)).reshape(5,4) # 4 time-dependent series
>>> time
array([ 20. , 51.25, 82.5 , 113.75, 145. ])
>>> data
array([[ 0. , 0.84147098, 0.90929743, 0.14112001],
[-0.7568025 , -0.95892427, -0.2794155 , 0.6569866 ],
[ 0.98935825, 0.41211849, -0.54402111, -0.99999021],
[-0.53657292, 0.42016704, 0.99060736, 0.65028784],
[-0.28790332, -0.96139749, -0.75098725, 0.14987721]])
>>>
>>> ind = data.argmax(axis=0) # index of the maxima for each series
>>> ind
array([2, 0, 3, 1])
>>>
>>> time_max = time[ ind] # times corresponding to the maxima
>>>
>>> data_max = data[ind, xrange(data.shape[1])] # => data[ind[0],0], data[ind[1],1]...
>>>
>>> time_max
array([ 82.5 , 20. , 113.75, 51.25])
>>> data_max
array([ 0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
>>>
>>> np.all(data_max == data.max(axis=0))
True
>>> let time = linspace 5 (20.0, 145.0) :: Vector R
>>> let ydata = cmap sin ((5><4) [0..]) :: Matrix R -- data is a protected word
>>> time
[20.0,51.25,82.5,113.75,145.0]
>>> ydata
(5><4)
[ 0.0, 0.8414709848078965, 0.9092974268256817, 0.1411200080598672
, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891
, 0.9893582466233818, 0.4121184852417566, -0.5440211108893698, -0.9999902065507035
, -0.5365729180004349, 0.4201670368266409, 0.9906073556948704, 0.6502878401571168
, -0.2879033166650653, -0.9613974918795568, -0.750987246771676, 0.14987720966295234 ]
>>> let ind = fmap maxIndex (toColumns ydata)
>>> ind
[2,0,3,1]
>>> let time_max = flatten ((asRow time) ?? (All, Pos (idxs ind)))
>>> let ydata_max = takeDiag (ydata ?? (Pos (idxs ind), All))
>>> time_max
[82.5,20.0,113.75,51.25]
>>> ydata_max
[0.9893582466233818,0.8414709848078965,0.9906073556948704,0.6569865987187891]
>>> (toList ydata_max) == (fmap maxElement (toColumns ydata))
True
>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> a[[1,3,4]] = 0
>>> a
array([0, 0, 2, 0, 0])
>>> a = np.arange(5)
>>> a[[0,0,2]]=[1,2,3]
>>> a
array([2, 1, 3, 3, 4])
>>> a = np.arange(5)
>>> a[[0,0,2]]+=1
>>> a
array([1, 1, 3, 3, 4])
>>> let a = 5 |> [0..] :: Vector Z
>>> a
[0,1,2,3,4]
>>> let a' = accum a const (zip [1,3,4] (repeat 0))
>>> a'
[0,0,2,0,0]
>>> let a' = accum a const (zip [1,2,3] [0,0,2])
>>> a'
[0,0,0,2,4]
>>> let a' = accum a (+) (zip [0,0,2] (repeat 1))
>>> a' -- this DOES work, since we hit the 0 index twice mutably
[2,1,3,3,4]
Indexing with Boolean Arrays¶
>>> a = np.arange(12).reshape(3,4)
>>> b = a > 4
>>> b # b is a boolean with a's shape
array([[False, False, False, False],
[False, True, True, True],
[ True, True, True, True]], dtype=bool)
>>> a[b] # 1d array with the selected elements
array([ 5, 6, 7, 8, 9, 10, 11])
>>> a[b] = 0 # All elements of 'a' higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
[4, 0, 0, 0],
[0, 0, 0, 0]])
>>> let a = (3><4) [0..] :: Matrix Z
>>> let b = (fmap (fmap (>4))) (toLists a) -- gives a [[Bool]], which is not that useful
>>> let b = find (>4) a -- better than just Matrix Bool, which does not work in hmatrix
>>> b -- a [IndexOf c] is more idiomatic
[(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3)]
>>> fromList (fmap (atIndex a) b)
[5,6,7,8,9,10,11]
>>> accum a const (zip b (repeat 0))
(3><4)
[ 0, 1, 2, 3
, 4, 0, 0, 0
, 0, 0, 0, 0 ]
>>> a = np.arange(12).reshape(3,4)
>>> b1 = np.array([False,True,True]) # first dim selection
>>> b2 = np.array([True,False,True,False]) # second dim selection
>>>
>>> a[b1,:] # selecting rows
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[b1] # same thing
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[:,b2] # selecting columns
array([[ 0, 2],
[ 4, 6],
[ 8, 10]])
>>>
>>> a[b1,b2] # a weird thing to do
array([ 4, 10])
>>> let a = (3><4) [0..] :: Matrix Z
>>> let b1' = [False,True,True]
>>> let b2' = [True,False,True,False]
>>> import Data.List (elemIndices)
>>> let helper = elemIndices True
>>> let b1 = helper b1'
>>> let b2 = helper b2'
>>> a ?? (Pos (idxs b1), All)
(2><4)
[ 4, 5, 6, 7
, 8, 9, 10, 11 ]
>>> a ? b1
(2><4)
[ 4, 5, 6, 7
, 8, 9, 10, 11 ]
>>> a ?? (All, Pos (idxs b2))
(3><2)
[ 0, 2
, 4, 6
, 8, 10 ]
>>> a ?? (Pos (idxs b1), Pos (idxs b2)) -- unlike numpy, will return matrix that matches any combination from selections
(2><2)
[ 4, 6
, 8, 10 ]
>>> (fromList . fmap (atIndex a)) (zip b1 b2) -- this will give you the numpy result, the zipped indexing of a matrix to give a vector
[4,10]