Get element from array based on list of indices - python

z = np.arange(15).reshape(3,5)
indexx = [0,2]
indexy = [1,2,3,4]
zz = []
for i in indexx:
for j in indexy:
zz.append(z[i][j])
Output:
zz >> [1, 2, 3, 4, 11, 12, 13, 14]
This essentially flattens the array but only keeping the elements that have indicies present in the two indices list.
This works, but it is very slow for larger arrays/list of indicies. Is there a way to speed this up using numpy?
Thanks.
Edited to show desired output.

A list of integers can be used to access the entries of interest for numpy arrays.
z[indexx][:,indexy].flatten()

x = {"apple", "banana", "cherry"}
y = {"google", "microsoft", "apple"}
z = x.intersection(y)
print(z)
z => apples
If I understand you correctly, just use Python set. And then cast it to list.

Indexing in several dimensions at once requires broadcasting the indices against each other. np.ix_ is a handy tool for doing this:
In [127]: z
Out[127]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In [128]: z[np.ix_(indexx, indexy)]
Out[128]:
array([[ 1, 2, 3, 4],
[11, 12, 13, 14]])
Converting that to 1d is a trivial ravel() task.
Look at the ix_ produces, here it's a (2,1) and (1,4) array. You can construct such arrays 'from-scratch':
In [129]: np.ix_(indexx, indexy)
Out[129]:
(array([[0],
[2]]),
array([[1, 2, 3, 4]]))

Related

Reverse Index through a numPy ndarray

I have a n x n dimensional numpy array of eigenvectors as columns, and want to return the last v of them as another array. However, they are currently in ascending order, and I wish to return them in descending order.
Currently, I'm attempting to index as follows
eigenvector_array[:,-1:-v]
But this doesn't seem to be working. Is there a more efficient way to do this?
Given a 2d array:
In [44]: x = np.arange(15).reshape(3,5);x
Out[44]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
the last 3 columns:
In [45]: x[:,-3:]
Out[45]:
array([[ 2, 3, 4],
[ 7, 8, 9],
[12, 13, 14]])
and reversing their order:
In [46]: x[:,-3:][:,::-1]
Out[46]:
array([[ 4, 3, 2],
[ 9, 8, 7],
[14, 13, 12]])
Or we could reverse the order, and take the first n. x[:,::-1][:,:3]
I tried combining the selection and order, but getting the end points is trickier. Separating the operations is easier.
x[:,:-4:-1]
Lets re-write this to make it a little less confusing.
eigenvector_array[:,-1:-v]
to:
eigenvector_array[:][-1:-v]
Now remember how slicing works in python:
[start:stop:step]
If you set step. to -1 it will return them in reverse, so:
eigenvector_array[:,-1:-v:-1] should be your answer.

python : numpy n-array : arranged values

i would like to get an multidimentional array in arr1.shape = (x,y)
which would be filled with values like from np.arange(z), where z is number of spaces in arr1.
it is known that, that i could make
arr2 = np.random.randn(x,y)
but then the values would be random...
Is there any straight way, which allows me not to iterate through the array?
You could use numpy.reshape to take the result of numpy.arange and reshape into (x,y) dimensions
>>> import numpy as np
>>> x = 5
>>> y = 3
>>> np.reshape(np.arange(x*y), (x,y))
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]])

Slicing a different range at each index of a multidimensional numpy array [duplicate]

This question already has answers here:
Selecting Random Windows from Multidimensional Numpy Array Rows
(2 answers)
Closed 3 years ago.
I have an m x n numpy array arr, and for each column of arr, I have a given range of rows that I want to access.
I have an n x 1 array vec that describes when this range starts.
The range has some constant duration d.
How can I extract this d x n array of interest efficiently?
Can this be done by clever slicing?
My initial thought was to try something like:
arr = np.tile(np.arange(10),(4,1)).T
vec = np.array([3,4,5,4])
d = 3
vec_2 = vec+d
out = arr[vec:vec2,np.arange(n)]
But this gives the following error:
TypeError: only integer scalar arrays can be converted to a scalar index
The desired output would be the following array:
array([[3, 4, 5, 4],
[4, 5, 6, 5],
[5, 6, 7, 6],
[6, 7, 8, 7])
I could loop over d, but performance is important for this piece of code so I would prefer to vectorize it.
In [489]: arr=np.arange(24).reshape(6,4)
In [490]: vec=np.array([0,2,1,3])
Taking advantage of the recent expansion of linspace to generate several arrays:
In [493]: x = np.linspace(vec,vec+2,3).astype(int)
In [494]: x
Out[494]:
array([[0, 2, 1, 3],
[1, 3, 2, 4],
[2, 4, 3, 5]])
In [495]: arr[x, np.arange(4)]
Out[495]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])
the column iteration approach:
In [498]: np.stack([arr[i:j,k] for k,(i,j) in enumerate(zip(vec,vec+3))],1)
Out[498]:
array([[ 0, 9, 6, 15],
[ 4, 13, 10, 19],
[ 8, 17, 14, 23]])

Arbitary 1D slices (elements along an axis) across an ndarray - NumPy

There are a few questions I've found that are close to what I am asking but they are different enough that they don't seem to solve my problem. I am trying to grab a 1d slice along one axis for an ndarray. As an example for a 3d array
[[[ 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,25,26]]]
I want the following 1d slices
[0,1,2]
...
[24,25,26]
[0,3,6]
...
[20,23,26]
[0,9,18]
...
[8,17,26]
which effectively equates to the following (for a 3d arrays):
ary[i,j,:]
ary[i,:,k]
ary[:,j,k]
I want this to generalize to an array of n dimensions
(for a 2d array we would get ary[i,:] and ary[:,j], etc.)
Is there a numpy function that lets me do this?
EDIT: Corrected the 2nd dimension indexing
We could permute axes by selecting each one of the axes one at a time pushing it at the end and reshape. We would make use of ndarray.ndim to generalize to generic n-dim ndarrays. Also, np.transpose would be useful here to permute axes and np.roll to get rolled axes order. The implementation would be quite simple and is listed below -
# a is input ndarray
R = np.arange(a.ndim)
out = [np.transpose(a,np.roll(R,i)).reshape(-1,a.shape[i]) for i in R]
Sample run -
In [403]: a = np.arange(27).reshape(3,3,3)
In [325]: R = np.arange(a.ndim)
In [326]: out = [np.transpose(a,np.roll(R,i)).reshape(-1,a.shape[i]) for i in R]
In [327]: out[0]
Out[327]:
array([[ 0, 1, 2],
[ 3, 4, 5],
...
[24, 25, 26]])
In [328]: out[1]
Out[328]:
array([[ 0, 3, 6],
[ 9, 12, 15],
....
[20, 23, 26]])
In [329]: out[2]
Out[329]:
array([[ 0, 9, 18],
[ 1, 10, 19],
....
[ 8, 17, 26]])

Most efficient way to test whether each element from one 1-d array exists in corresponding row of another 2-d array, using python

I would like to know the most efficient way to test whether each element from one 1-d array exists in corresponding row of another 2-d array, using python
Specifically, I have two arrays. The first is an 1-d array of integers. The second is a 2-d array of integers.
Sample input:
[1, 4, 12, 9] # array 1
[[1, 12, 299],
[2, 5, 11],
[1, 3, 11],
[0, 1, 9]] # array 2
Expected output:
[True, False, False, True]
You can reshape a to 2d array, compare with b and then check if there's any True in each row:
np.equal(np.reshape(a, (-1,1)), b).any(axis=1)
a = [1, 4, 12, 9] # array 1
​
b = [[1, 12, 299],
[2, 5, 11],
[1, 3, 11],
[0, 1, 9]]
np.equal(np.reshape(a, (-1,1)), b).any(1)
# array([ True, False, False, True], dtype=bool)
This is a fairly pythonic solution to your problem. Note that this works virtually identically for numpy arrays and standard lists. Definitely not the most efficient solution for huge numpy arrays, but I doubt this would be any type of performance bottleneck, and pursuing premature optimization over readability is a cardinal sin.
a = [1, 4, 12, 9]
b = [
[1, 12, 299],
[2, 5, 11],
[1, 3, 11],
[0, 1, 9]
]
c = [x in y for x, y in zip(a,b)]

Categories

Resources