MrCheatak
MrCheatak

Reputation: 179

How to manually select values from an array

For example I have a matrix array

a=np.arrange(25).shape(5,5)
[[ 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]]

How do I make an 1D array of elements that I would like to choose manually? For example [2,3], [4,1], [1,0] and [2,2], so I get the following:

b=[13, 21, 5, 12]

The array should a reference rather than a copy.

Upvotes: 0

Views: 324

Answers (3)

MrCheatak
MrCheatak

Reputation: 179

First of all, I've found that constructing a non-contiguous view to a Numpy array is not natively possible, because Numpy efficiently utilises contiguous memory layout of an array, which enables dramatic speed increase.

Here's a solution I found that works the best so far: Instead of having a view to an array, I construct a collection indices, that I would like to process, [2,3], [4,1], [1,0], [2,2]. The collection type I have chosen are Sets, due to exclusion of duplicates and set().add and set().discard methods that do not require search. Keeping order was not necessary.

To use them for indexing an array they have to be casted from a set of tuples set{(2,3),(4,1),(1,0),(2,2)} to a tuple of arrays (ndarray([2,4,1,2], ndarray[3,1,0,2]).

Which can be achieved by unzipping a set and constructing a tuple of arrays:

import numpy as np
a=np.arrange(25).shape(5,5)
>>>[[ 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]]

my_set = {(2,3),(4,1),(1,0),(2,2)}
uzip_set = list(zip(*my_set))
seq_from_set = (np.asarray(uzip_set[0]),np.asarray(uzip_set[1]))
print(seq_from_set)
>>>(array[2,4,1,2], array[3,1,0,2])

And array a can be manipulated by providing such a sequence of indices:

b = a[seq_from_set]
print(b)
>>>array[13,21,5,12]  
a[seq_from_set] = 0
print(a)   
 >>>[[ 0  1  2  3  4]
     [ 0  6  7  8  9]
     [10 11  0  0 14]
     [15 16 17 18 19]
     [20  0 22 23 24]]

The solution is a bit sophisticated compared to something native, but works surprisingly fast. This allows an easy management of the collection of indices and supports quick conversion to a stream of indices on demand.

Upvotes: 0

a=np.arange(25).reshape(5,5)
search=[[2,3], [4,1], [1,0], [2,2]]
for row,col in search:
    print(row,col, a[row][col])

output:

r c result
2 3 13
4 1 21
1 0 5
2 2 12

Upvotes: 0

You can make a function for this.

# defining the function
def get_value(matrix, row_list, col_list):
    for i, j in zip(row_list, col_list):
        return matrix[row_list, col_list]

# initializing the array
a = np.arange(0, 25, 1).reshape(5, 5)

# getting the required values and printing
b = get_value(a, [2,4,1,0], [3,1,0,2])

# output
print(b)

Edit

I'll let the previous answer be as is, just in case if anyone else stumbles upon that and needs it.

What the question wants is to give a value from b (i.e. b[0] which is 13) and change the value from the original matrix a based on the index of that passed value from b in a.

def change_the_value(old_mat, val_to_change, new_val):
    mat_coor = np.array(np.matrix(np.where(old_mat == val_to_change)).T)[0]
    old_mat[mat_coor[0], mat_coor[1]] = new_val
 
a = np.arange(0, 25, 1).reshape(5,5)
b = [13, 16, 5, 12]

change_the_value(a, b[0], 0)

Upvotes: 1

Related Questions