Suppose I have
[[array([x1, y1]), z1]
[array([x2, y1]), z2]
......
[array([xn, yn]), zn]
]
And I want to find the index of array([x5, y5]). How can find effieciently using NumPy?
To start off, owing to the mixed data format, I don't think you can extract the arrays in a vectorized manner. Thus, you can use loop comprehension to extract the first element corresponding to the arrays from each list element as a 2D array. So, let's say A is the input list, we would have -
arr = np.vstack([a[0] for a in A])
Then, simply do the comparison in a vectorized fashion using NumPy's broadcasting feature, as it will broadcast that comparison along all the rows and look all matching rows with np.all(axis=1). Finally, use np.flatnonzero to get the final indices. Thus, the final peace of the puzzle would be -
idx = np.flatnonzero((arr == search1D).all(1))
You can read up on the answers to this post to see other alternatives to get indices in such a 1D array searching in 2D array problem.
Sample run -
In [140]: A
Out[140]:
[[array([3, 4]), 11],
[array([2, 1]), 12],
[array([4, 2]), 16],
[array([2, 1]), 21]]
In [141]: search1D = [2,1]
In [142]: arr = np.vstack([a[0] for a in A]) # Extract 2D array
In [143]: arr
Out[143]:
array([[3, 4],
[2, 1],
[4, 2],
[2, 1]])
In [144]: np.flatnonzero((arr == search1D).all(1)) # Finally get indices
Out[144]: array([1, 3])
Related
I have the following array and a list of indices
my_array = np.array([ [1,2], [3,4], [5,6], [7,8] ])
indices = np.array([0,2])
I can get the values of the array corresponding to my indices by just doing my_array[indices], which gives me the expected result
array([[1, 2],
[5, 6]])
Now I want to get the complement of it. As mentioned in one of the answers, doing
my_array[~indices]
Will not give the expected result [[3,4],[7,8]].
I was hoping this could be done in a 1-liner way, without having to define additional masks.
You can use numpy.delete. It returns a new array with sub-arrays along an axis deleted.
complement = np.delete(my_array, indices, axis=0)
>>> np.delete(my_array, indices, axis=0)
array([[3, 4],
[7, 8]])
I want to get the index of a 2d array which contains a specific array. In this case I want to know where in the array array the array [[4, 5], 6] is but only based on the inner most array [4, 5] so that I get its position even if instead of the six it would be an eight.
This is my code so far:
import numpy as np
array = np.array([[[1, 2], 3], [[4, 5], 6], [[7, 8], 9]])
print(np.where(array == [4, 5]))
but as an output I get:
(array([], dtype=int32), array([], dtype=int32))
and the output I want is the following:
(array([1], dtype=int32), array([0], dtype=int32))
The issue is that you are working with a dtype object where your first numpy column contains list objects.
You can create a vectorized function to check each object individually.
f = np.vectorize(lambda x: x==[4,5])
idx = np.where(f(array))
idx
(array([1]), array([0]))
You can also use a list comprehension after flattening out the array and then checking each object against [4,5]. Then you could use np.where or just plain simple boolean check to get the index in that flat list, which you could unravel_index to get the position in the 2D array. (I am using np.where because you want to use it)
check = [i==[4,5] for i in array.ravel()]
np.unravel_index(*np.where(check), array.shape)
(array([1]), array([0]))
In Python, i need to split two rows in half, take the first half from row 1 and second half from row 2 and concatenate them into an array which is then saved as a row in another 2d array. for example
values=np.array([[1,2,3,4],[5,6,7,8]])
will become
Y[2,:]= ([1,2,7,8])) // 2 is arbitrarily chosen
I tried doing this with concatenate but got an error
only integer scalar arrays can be converted to a scalar index
x=values.shape[1]
pop[y,:]=np.concatenate(values[temp0,0:int((x-1)/2)],values[temp1,int((x-1)/2):x+1])
temp0 and temp1 are integers, and values is a 2d integer array of dimensions (100,x)
np.concatenate takes a list of arrays, plus a scalar axis parameter (optional)
In [411]: values=np.array([[1,2,3,4],[5,6,7,8]])
...:
Nothing wrong with how you split values:
In [412]: x=values.shape[1]
In [413]: x
Out[413]: 4
In [415]: values[0,0:int((x-1)/2)],values[1,int((x-1)/2):x+1]
Out[415]: (array([1]), array([6, 7, 8]))
wrong:
In [416]: np.concatenate(values[0,0:int((x-1)/2)],values[1,int((x-1)/2):x+1])
----
TypeError: only integer scalar arrays can be converted to a scalar index
It's trying to interpret the 2nd argument as an axis parameter, hence the scalar error message.
right:
In [417]: np.concatenate([values[0,0:int((x-1)/2)],values[1,int((x-1)/2):x+1]])
Out[417]: array([1, 6, 7, 8])
There are other concatenate front ends. Here hstack would work the same. np.append takes 2 arrays, so would work - but too often people use it wrongly. np.r_ is another front end with different syntax.
The indexing might be clearer with:
In [423]: idx = (x-1)//2
In [424]: np.concatenate([values[0,:idx],values[1,idx:]])
Out[424]: array([1, 6, 7, 8])
Try numpy.append
numpy.append Documentation
np.append(values[temp0,0:int((x-1)/2)],values[temp1,int((x-1)/2):x+1])
You don't need splitting and/or concatenation. Just use indexing:
In [47]: values=np.array([[1,2,3,4],[5,6,7,8]])
In [48]: values[[[0], [1]],[[0, 1], [-2, -1]]]
Out[48]:
array([[1, 2],
[7, 8]])
Or ravel to get the flattened version:
In [49]: values[[[0], [1]],[[0, 1], [-2, -1]]].ravel()
Out[49]: array([1, 2, 7, 8])
As a more general approach you can also utilize np.r_ as following:
In [61]: x, y = values.shape
In [62]: values[np.arange(x)[:,None],[np.r_[0:y//2], np.r_[-y//2:0]]].ravel()
Out[62]: array([1, 2, 7, 8])
Reshape to split the second dimension in two; stack the part you want.
a = np.array([[1,2,3,4],[5,6,7,8]])
b = a.reshape(a.shape[0], a.shape[1]//2, 2)
new_row = np.hstack([b[0,0,:], b[1,1,:]])
#new_row = np.hstack([b[0,0], b[1,1]])
I want to get slices from a numpy array and assign them to a larger array.
The slices should be 64 long and should be taken out evenly from the source array.
I tried the following:
r = np.arange(0,magnitude.shape[0],step)
magnitudes[counter:counter+len(r),ch] = magnitude[r:r+64]
I get the following error when I tried the above code:
TypeError: only integer arrays with one element can be converted to an index
What is the most pythonic way to achieve the slicing?
magnitude[r:r+64] where r is an array is wrong. The variables in the slice must be scalars, magnitude[3:67], not magnitude[[1,2,3]:[5,6,7]].
If you want to collect multiple slices you have to do something like
In [345]: x=np.arange(10)
In [346]: [x[i:i+3] for i in range(4)]
Out[346]: [array([0, 1, 2]), array([1, 2, 3]), array([2, 3, 4]), array([3, 4, 5])]
In [347]: np.array([x[i:i+3] for i in range(4)])
Out[347]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
Other SO questions have explored variations on this, trying to find the fastest, but it's hard to get around some sort loop or list comprehension.
I'd suggest working with this answer, and come back with a new question, and a small working example, if you think you need more speed.
If I have a and b:
a=[[1,2,3],
[4,5,6],
[7,8,9]]
b=8.1
and I want to find the index of the value b in a, I can do:
nonzero(abs(a-b)<0.5)
to get (2,1) as the index, but what do I do if b is a 1d or 2d array? Say,
b=[8.1,3.1,9.1]
and I want to get (2,1),(0,2),(2,2)
In general I expect only one match in a for every value of b. Can I avoid a for loop?
Use a list comprehension:
[nonzero(abs(x-a)<0.5) for x in b]
Vectorized approach with NumPy's broadcasting -
np.argwhere((np.abs(a - b[:,None,None])<0.5))[:,1:]
Explanation -
Extend b from a 1D to a 3D case with None/np.newaxis, keeping the elements along the first axis.
Perform absolute subtractions with the 2D array a, thus bringing in broadcasting and leading to a 3D array of elementwise subtractions.
Compare against the threshold of 0.5 and get the indices corresponding to matches along the last two axes and sorted by the first axis with np.argwhere(...)[:,1:].
Sample run -
In [71]: a
Out[71]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [72]: b
Out[72]: array([ 8.1, 3.1, 9.1, 0.7])
In [73]: np.argwhere((np.abs(a - b[:,None,None])<0.5))[:,1:]
Out[73]:
array([[2, 1],
[0, 2],
[2, 2],
[0, 0]])