I have a numpy array like this:
A = array([[1, 3, 2, 7],
[2, 4, 1, 3],
[6, 1, 2, 3]])
I would like to sort the rows of this matrix in descending order and get the arguments of the sorted matrix like this:
As = array([[3, 1, 2, 0],
[1, 3, 0, 2],
[0, 3, 2, 1]])
I did the following:
import numpy
A = numpy.array([[1, 3, 2, 7], [2, 4, 1, 3], [6, 1, 2, 3]])
As = numpy.argsort(A, axis=1)
But this gives me the sorting in ascending order. Also, after I spent some time looking for a solution in the internet, I expect that there must be an argument to argsort function from numpy that would reverse the order of sorting. But, apparently there is no such argument! Why!?
There is an argument called order. I tried, by guessing, numpy.argsort(..., order=reverse) but it does not work.
I looked for a solution in previous questions here and I found that I can do:
import numpy
A = numpy.array([[1, 3, 2, 7], [2, 4, 1, 3], [6, 1, 2, 3]])
As = numpy.argsort(A, axis=1)
As = As[::-1]
For some reason, As = As[::-1] does not give me the desired output.
Well, I guess it must be simple but I am missing something.
How can I sort a numpy array in descending order?
Just multiply your matrix by -1 to reverse order:
[In]: A = np.array([[1, 3, 2, 7],
[2, 4, 1, 3],
[6, 1, 2, 3]])
[In]: print( np.argsort(-A) )
[Out]: [[3 1 2 0]
[1 3 0 2]
[0 3 2 1]]
Related
numpy.unique has an optional argument return_counts. From the docs:
return_counts bool, optional If True, also return the number of times
each unique item appears in ar.
New in version 1.9.0.
Which is straightforward for a 1-D array. However, I'm trying to the unique values and counts for each row of a matrix. Here is a sample matrix:
m_sample = np.array([
[1, 2, 1],
[2, 2, 2],
[3, 3, 3],
[1, 4, 5],
])
When I apply np.unique:
np.unique(m_sample, axis=1, return_counts=True)
(array([[1, 1, 2],
[2, 2, 2],
[3, 3, 3],
[1, 5, 4]]), array([1, 1, 1]))
I'm not really sure what the returned matrix here represents, much less so the counts array. Is this perhaps a bug in numpy (or maybe a case the developer did not consider)? Am I misunderstanding how to use the parameters in this case?
When you specify an axis, np.unique returns unique subarrays indexed along this axis. To see is better, assume that one of the rows repeats:
m_sample = np.array([
[1, 2, 1],
[2, 2, 2],
[3, 3, 3],
[1, 4, 5],
[1, 2, 1]
])
In such case np.unique(m_sample, axis=0, return_counts=True) gives:
(array([[1, 2, 1],
[1, 4, 5],
[2, 2, 2],
[3, 3, 3]]),
array([2, 1, 1, 1]))
The first element of this tuple lists unique rows of the array, and the second how many times each row appears in the array. In this example, the row [1, 2, 1] is repeated twice.
To get unique values in each row you can try, for example, the following:
import numpy as np
m_sample = np.array([
[1, 2, 1],
[2, 2, 2],
[3, 3, 3],
[1, 4, 5]
])
s = np.sort(m_sample, axis=1)
mask = np.full(m_sample.shape, True)
mask[:, 1:] = s[:, :-1] != s[:, 1:]
np.split(s[mask], np.cumsum(mask.sum(axis=1)))[:-1]
It gives:
[array([1, 2]), array([2]), array([3]), array([1, 4, 5])]
I'm new to Python and could use some help. I tried to find a similar question but apparently, they differ by a bit and the answers don’t work for my problem. I use PyCharm and Python 3.8.
Cutting to the case:
I have a list of matrices and I want to average all the matrix values. I already struggle with accessing the values.
A small test list looks like this:
data = [[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[2, 3, 4], [2, 3, 4], [2, 3, 4]],
[[3, 4, 5], [3, 4, 5], [3, 4, 5]],
[[4, 5, 6], [4, 5, 6], [4, 5, 6]]]
I tried to access all values at position (n, m) in the list and expect something like for (1,1) [2,3,4,5]
I tried to use:
print(data[:][1][1])
And got the result:
[2, 3, 4] which is one list entry short. Also, I think it's just data[1][1].
Which is not what I want to have.
Can someone tell me what I’m doing wrong?
When working with matrices in python I advice using numpy.
Your data is a list of four 3x3 matrices:
data = [
[
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]
],
[
[2, 3, 4],
[2, 3, 4],
[2, 3, 4]
],
[
[3, 4, 5],
[3, 4, 5],
[3, 4, 5]
],
[
[4, 5, 6],
[4, 5, 6],
[4, 5, 6]
],
]
We can easily convert this to a numpy array:
import numpy as np
data_np = np.array(data)
print(data_np.shape)
the last statement returns (4, 3, 3) -- equivalent structure to your data, a 3-dimensional array, where the first is index of a matrix, and the last two are indices of elements of each matrix. Now you can subsample along any dimension, including your desired result:
data_np[:, 1, 1]
which returns array([2, 3, 4, 5]). You can also cast it to a python list if needed through data_np[:, 1, 1].tolist()
There's also a pure python version of this, which I do not recommend using, but it might be a useful design pattern in less obvious cases. Using list comprehension we access each matrix, and then retrieve the interesting index.
[matrix[1][1] for matrix in data]
which returns a list [2, 3, 4, 5]
I suggest using the numpy package, which is great for doing all sorts of matrix and vector operations. It makes indexing alot easier.
Note that i added some enters in your data array to make it more readible.
Example:
import numpy as np
data = np.array(
[
[[1,2,3],[1,2,3],[1,2,3]],
[[2,3,4],[2,3,4],[2,3,4]],
[[3,4,5],[3,4,5],[3,4,5]],
[[4,5,6],[4,5,6],[4,5,6]]
]
)
print(data[:,1,1])
Outputs:
[2 3 4 5]
lists cannot be indexed in the same way as numpy arrays.
Have a look what is happening with your slices:
The first slice is just returning the whole list
data[:]
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[2, 3, 4], [2, 3, 4], [2, 3, 4]],
[[3, 4, 5], [3, 4, 5], [3, 4, 5]],
[[4, 5, 6], [4, 5, 6], [4, 5, 6]]]
the second slice is returning the second list (list indexes start at 0, so the index 1 is the second element)
data[:][1]
Out[46]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
The third slice is returning the second list, within the second list
data[:][1][1]
Out[47]: [2, 3, 4]
If you want to achieve what you are looking for with a list, you would use:
[x[1][1] for x in data]
[2, 3, 4, 5]
to loop through each list and select the second element of the first list.
However, it would be better to use numpy
import numpy as np
arr = np.array(data)
arr[:, 1, 1]
Out[56]: array([2, 3, 4, 5])
I'm looking to leverage numba to iterate over a large 2d array, where for iteration a subset of the array will be selected by [x, y] location (passed as an argument). I'm having trouble with structuring this the right way to play nice with numba, specifically when passing a list of lists as an argument into the method. Any pointers?
x_y_list = [[1, 2], [3, 4], [5, 6]]
array = ([[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6]])
#jit
def arrIndexing(array, x_y_list):
for index in x_y_list:
subset = array[index[0]-1:index[0]+1, index[1]-1:index[1]+1]
# do some other stuff
Something like this?
Should do well with Numba but I haven’t tested (did this on my phone which doesn’t support Numba)
import numpy as np
def xy():
x_y_list = np.array([[1, 2], [2, 4], [0, 5]])
array = np.array([[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6]])
for i,j in x_y_list:
print(array[np.ix_((i-1, i), (j-1, j))])
>>> xy()
[[2 3]
[2 3]]
[[4 5]
[4 5]]
[[5 6]
[5 6]]
The title is probably confusing. I have a reasonably large 3D numpy array. I'd like to cut it's size by 2^3 by binning blocks of size (2,2,2). Each element in the new 3D array should then contain the sum of the elements in it's respective block in the original array.
As an example, consider a 4x4x4 array:
input = [[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
... ]]]
(I'm only representing half of it to save space). Notice that all the elements with the same value constitute a (2x2x2) block. The output should be a 2x2x2 array such that each element is the sum of a block:
output = [[[8, 16],
[24, 32]],
... ]]]
So 8 is the sum of all 1's, 16 is the sum of the 2's, and so on.
There's a builtin to do those block-wise reductions - skimage.measure.block_reduce-
In [36]: a
Out[36]:
array([[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]],
[[1, 1, 2, 2],
[1, 1, 2, 2],
[3, 3, 4, 4],
[3, 3, 4, 4]]])
In [37]: from skimage.measure import block_reduce
In [39]: block_reduce(a, block_size=(2,2,2), func=np.sum)
Out[39]:
array([[[ 8, 16],
[24, 32]]])
Use other reduction ufuncs, say max-reduction -
In [40]: block_reduce(a, block_size=(2,2,2), func=np.max)
Out[40]:
array([[[1, 2],
[3, 4]]])
Implementing such a function isn't that difficult with NumPy tools and could be done like so -
def block_reduce_numpy(a, block_size, func):
shp = a.shape
new_shp = np.hstack([(i//j,j) for (i,j) in zip(shp,block_size)])
select_axes = tuple(np.arange(a.ndim)*2+1)
return func(a.reshape(new_shp),axis=select_axes)
I have a multidimension array that looks like this:
my_array = np.arange(2)[:,None,None] *np.arange(4)[:, None]*np.arange(8)
I am looking for a multidimensional equivalent of the 2-D argmax
In particular, I am looking for argmax of maxima along axis = 2. I tried reshaping first, but reshaping will completely destroy the original indices information of the entire array, so it probably won't work. I have no clue how to do it and need helps from you guys. Thank you in advance
EDIT: Desire output is:
[(0,0,0),(1,3,1),(1,3,2),(1,3,3),(1,3,4),(1,3,5),(1,3,6),(1,3,7)]
This exactly is the array of the indices of maxima along axis = 2
For finding such argmax indices along the last axis of a 3D ndarray, we can use something along these lines -
In [66]: idx = my_array.reshape(-1,my_array.shape[-1]).argmax(0)
In [67]: r,c = np.unravel_index(idx,my_array.shape[:-1])
In [68]: l = np.arange(len(idx))
In [69]: np.c_[r,c,l]
Out[69]:
array([[0, 0, 0],
[1, 3, 1],
[1, 3, 2],
[1, 3, 3],
[1, 3, 4],
[1, 3, 5],
[1, 3, 6],
[1, 3, 7]])
To extend this to a generic ndarray -
In [99]: R = np.unravel_index(idx,my_array.shape[:-1])
In [104]: np.hstack((np.c_[R],l[:,None]))
Out[104]:
array([[0, 0, 0],
[1, 3, 1],
[1, 3, 2],
[1, 3, 3],
[1, 3, 4],
[1, 3, 5],
[1, 3, 6],
[1, 3, 7]])