python - Find the row indexes of several values in a numpy array -
i have array x:
x = np.array([[4, 2], [9, 3], [8, 5], [3, 3], [5, 6]]) and wish find index of row of several values in array:
searched_values = np.array([[4, 2], [3, 3], [5, 6]]) for example result like:
[0,3,4] i have code doing this, think overly complicated:
x = np.array([[4, 2], [9, 3], [8, 5], [3, 3], [5, 6]]) searched_values = np.array([[4, 2], [3, 3], [5, 6]]) result = [] s in searched_values: idx = np.argwhere([np.all((x-s)==0, axis=1)])[0][1] result.append(idx) print(result) i found this answer similar question works 1d arrays.
is there way want in simpler way?
approach #1
one approach use numpy broadcasting, -
np.where((x==searched_values[:,none]).all(-1))[1] approach #2
a memory efficient approach convert each row linear index equivalents , using np.in1d, -
dims = x.max(0)+1 out = np.where(np.in1d(np.ravel_multi_index(x.t,dims),\ np.ravel_multi_index(searched_values.t,dims)))[0] approach #3
another memory efficient approach using np.searchsorted , same philosophy of converting linear index equivalents -
dims = x.max(0)+1 x1d = np.ravel_multi_index(x.t,dims) searched_valuesid = np.ravel_multi_index(searched_values.t,dims) sidx = x1d.argsort() out = sidx[np.searchsorted(x1d,searched_valuesid,sorter=sidx)] please note np.searchsorted method assumes there match each row searched_values in x.
how np.ravel_multi_index work?
this function gives linear index equivalent numbers. accepts 2d array of n-dimensional indices, set columns , shape of n-dimensional grid onto indices mapped , equivalent linear indices computed.
let's use inputs have problem @ hand. take case of input x , note first row of it. since, trying convert each row of x linear index equivalent , since np.ravel_multi_index assumes each column 1 indexing tuple, need transpose x before feeding function. since, number of elements per row in x in case 2, n-dimensional grid mapped onto 2d. 3 elements per row in x, had been 3d grid mapping , on.
to see how function compute linear indices, consider first row of x -
in [77]: x out[77]: array([[4, 2], [9, 3], [8, 5], [3, 3], [5, 6]]) we have shape of n-dimensional grid dims -
in [78]: dims out[78]: array([10, 7]) let's create 2-dimensional grid see how mapping works , linear indices computed np.ravel_multi_index -
in [79]: out = np.zeros(dims,dtype=int) in [80]: out out[80]: array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]) let's set first indexing tuple x, i.e. first row x grid -
in [81]: out[4,2] = 1 in [82]: out out[82]: array([[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]) now, see linear index equivalent of element set, let's flatten , use np.where detect 1.
in [83]: np.where(out.ravel())[0] out[83]: array([30]) this computed if row-major ordering taken account.
let's use np.ravel_multi_index , verify linear indices -
in [84]: np.ravel_multi_index(x.t,dims) out[84]: array([30, 66, 61, 24, 41]) thus, have linear indices corresponding each indexing tuple x, i.e. each row x.
choosing dimensions np.ravel_multi_index form unique linear indices
now, idea behind considering each row of x indexing tuple of n-dimensional grid , converting each such tuple scalar have unique scalars corresponding unique tuples, i.e. unique rows in x.
let's take @ x -
in [77]: x out[77]: array([[4, 2], [9, 3], [8, 5], [3, 3], [5, 6]]) now, discussed in previous section, considering each row indexing tuple. within each such indexing tuple, first element represent first axis of n-dim grid, second element second axis of grid , on until last element of each row in x. in essence, each column represent 1 dimension or axis of grid. if map elements x onto same n-dim grid, need consider maximum stretch of each axis of such proposed n-dim grid. assuming dealing positive numbers in x, such stretch maximum of each column in x + 1. + 1 because python follows 0-based indexing. so, example x[1,0] == 9 map 10th row of proposed grid. similarly, x[4,1] == 6 go 7th column of grid.
so, our sample case, had -
in [7]: dims = x.max(axis=0) + 1 # or x.max(0) + 1 in [8]: dims out[8]: array([10, 7]) thus, need grid of @ least shape of (10,7) our sample case. more lengths along dimensions won't hurt , give unique linear indices too.
concluding remarks : 1 important thing noted here if have negative numbers in x, need add proper offsets along each column in x make indexing tuples positive numbers before using np.ravel_multi_index.
Comments
Post a Comment