I would like to take the two smallest values from an array x. But when I use np.where:
A,B = np.where(x == x.min())[0:1]
I get this error:
ValueError: need more than 1 value to unpack
How can I fix this error? And do I need to arange numbers in ascending order in array?
You can use numpy.partition to get the lowest k+1 items:
A, B = np.partition(x, 1)[0:2] # k=1, so the first two are the smallest items
In Python 3.x you could also use:
A, B, *_ = np.partition(x, 1)
For example:
import numpy as np
x = np.array([5, 3, 1, 2, 6])
A, B = np.partition(x, 1)[0:2]
print(A) # 1
print(B) # 2
How about using sorted instead of np.where?
A,B = sorted(x)[:2]
There are two errors in the code. The first is that the slice is [0:1] when it should be [0:2]. The second is actually a very common issue with np.where. If you look into the documentation, you will see that it always returns a tuple, with one element if you only pass one parameter. Hence you have to access the tuple element first and then index the array normally:
A,B = np.where(x == x.min())[0][0:2]
Which will give you the two first indices containing the minimum value. If no two such indices exist you will get an exception, so you may want to check for that.
Related
My array looks like this:
a = ([1,2],[2,3],[4,5],[3,8])
I did the following to delete odd indexes :
a = [v for i, v in enumerate(a) if i % 2 == 0]
but it dives me now two different arrays instead of one two dimensional:
a= [array([1, 2]), array([4, 5])]
How can I keep the same format as the beginning? thank you!
That is as simple as
a[::2]
which yields the lines with even index.
Use numpy array indexing, not comprehensions:
c = a[list(range(0,len(a),2)),:]
If you define c as the output of a list comprehension, it will return a list of one-dimensional numpy arrays. Instead, using the proper indexing maintains the result a numpy array.
Note than instead of "deleting" the odd indices, what we do is specify what to keep: take all lines with an even index (the list(range(0,len(a),2)) part) and for each line take all elements (the : part)
I tried doing this in python, but I get an error:
import numpy as np
array_to_filter = np.array([1,2,3,4,5])
equal_array = np.array([1,2,5,5,5])
array_to_filter[equal_array]
and this results in:
IndexError: index 5 is out of bounds for axis 0 with size 5
What gives? I thought I was doing the right operation here.
I am expecting that if I do
array_to_filter[equal_array]
That it would return
np.array([1,2,5])
If I am not on the right track, how would I get it to do that?
In the last statement the indices for your array are 1,2,5,5 and 5. Index 5 refers to 6th element in the array while you have only 5 elements. array_to_filter[5] does not exist.
[i for i in np.unique(equal_array) if i in array_to_filter]
would return the answer you want. This returns each of the unique value in equal_array if it also exist in array_to_filter
If array_to_filter is guaranteed to have unique values, you can do:
>>> array_to_filter[np.in1d(array_to_filter, equal_array)]
array([1, 2, 5])
From the documentation: np.in1d can be considered as an element-wise function version of the python keyword in, for 1-D sequences. in1d(a, b) is roughly equivalent to np.array([item in b for item in a]).
I have two arrays, one is a matrix of index pairs,
a = array([[[0,0],[1,1]],[[2,0],[2,1]]], dtype=int)
and another which is a matrix of data to access at these indices
b = array([[1,2,3],[4,5,6],[7,8,9]])
and I want to able to use the indices of a to get the entries of b. Just doing:
>>> b[a]
does not work, as it gives one row of b for each entry in a, i.e.
array([[[[1,2,3],
[1,2,3]],
[[4,5,6],
[4,5,6]]],
[[[7,8,9],
[1,2,3]],
[[7,8,9],
[4,5,6]]]])
when I would like to use the index pair in the last axis of a to give the two indices of b:
array([[1,5],[7,8]])
Is there a clean way of doing this, or do I need to reshape b and combine the columns of a in a corresponding manner?
In my actual problem a has about 5 million entries, and b is 100-by-100, I'd like to avoid for loops.
Actually, this works:
b[a[:, :, 0],a[:, :, 1]]
Gives array([[1, 5],
[7, 8]]).
For this case, this works
tmp = a.reshape(-1,2)
b[tmp[:,0], tmp[:,1]]
A more general solution, whenever you want to use a 2D array of indices of shape (n,m) with arbitrary large dimension m, named inds, in order to access elements of another 2D array of shape (n,k), named B:
# array of index offsets to be added to each row of inds
offset = np.arange(0, inds.size, inds.shape[1])
# numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C
Result = np.take(B, offset[:,np.newaxis]+inds)
Another solution, which doesn't use np.take and I find more intuitive, is the following:
B[np.expand_dims(np.arange(B.shape[0]), -1), inds]
The advantage of this syntax is that it can be used both for reading elements from B based on inds (like np.take), as well as for assignment.
You can test this by using, e.g.:
B = 1/(np.arange(n*m).reshape(n,-1) + 1)
inds = np.random.randint(0,B.shape[1],(B.shape[0],B.shape[1]))
I have a list of arrays like:
a = [array([6,2]),array([8,3]),array([4,2])]
I tried max(a) which returns the following error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I want it to return either a list or array like:
In: max(a)
Out: [8,3]
I don't want to convert the inner arrays to list, because the size of the list is very big. Also I purposefully created like that to perform array operations.
The easiest way is to convert to tuple/lists for the sake of comparison (or implement the comparison yourself):
>>> max(a, key=tuple)
array([8, 3])
Note this is the builtin max and not np.max
EDIT:
For multi dimensional arrays, use the .tolist method:
max(a, key=operator.methodcaller('tolist'))
Defining max on arrays is, as it says in the exception, ambiguous. If we have the following arrays: [6, 2], [5, 1], then I guess the output should be [6, 2], but if we have the following example: [6, 2], [7, 1] what would then the output have to be.
In fact there are so many different definitions of max here. If we take the arrays to be vectors then max can be the magnitude of them, or the vector that has maximum x coord, etc. Max can just as well compare the length of the arrays in the list and return the one with most elements or in the case of a tie the first one of the ones with equal length.
My suggestion is to create a class abstracting your array structures and define the max operation there with exactly the outcome you expect.
To have the max array along with the idx, this is what i'm using now:
a = [array([6,2]),array([8,3]),array([4,2])]
In: max_a = map(max, a)
Out: max_a = [6,8,4]
In: idx = max_a.index(max(max_a))
Out: idx = 1
In: result = a[idx]
Out: reusult = [8,3]
python 3.2
a=[([6,2]),([8,3]),([4,2])]
max(a)
Its working well
Say that I have 4 numpy arrays
[1,2,3]
[2,3,1]
[3,2,1]
[1,3,2]
In this case, I've determined [1,2,3] is the "minimum array" for my purposes, as it is one of two arrays with lowest value at index 0, and of those two arrays it has the the lowest index 1. If there were more arrays with similar values, I would need to compare the next index values, and so on.
How can I extract the array [1,2,3] in that same order from the pile?
How can I extend that to x arrays of size n?
Thanks
Using the python non-numpy .sort() or sorted() on a list of lists (not numpy arrays) automatically does this e.g.
a = [[1,2,3],[2,3,1],[3,2,1],[1,3,2]]
a.sort()
gives
[[1,2,3],[1,3,2],[2,3,1],[3,2,1]]
The numpy sort seems to only sort the subarrays recursively so it seems the best way would be to convert it to a python list first. Assuming you have an array of arrays you want to pick the minimum of you could get the minimum as
sorted(a.tolist())[0]
As someone pointed out you could also do min(a.tolist()) which uses the same type of comparisons as sort, and would be faster for large arrays (linear vs n log n asymptotic run time).
Here's an idea using numpy:
import numpy
a = numpy.array([[1,2,3],[2,3,1],[3,2,1],[1,3,2]])
col = 0
while a.shape[0] > 1:
b = numpy.argmin(a[:,col:], axis=1)
a = a[b == numpy.min(b)]
col += 1
print a
This checks column by column until only one row is left.
numpy's lexsort is close to what you want. It sorts on the last key first, but that's easy to get around:
>>> a = np.array([[1,2,3],[2,3,1],[3,2,1],[1,3,2]])
>>> order = np.lexsort(a[:, ::-1].T)
>>> order
array([0, 3, 1, 2])
>>> a[order]
array([[1, 2, 3],
[1, 3, 2],
[2, 3, 1],
[3, 2, 1]])