A one-line solution for editing an array of numpy counts? (Python)

I want to create a numpy array that contains how many times a value (between 1-3) occurs in a specific place. For example, if I have:

a = np.array([[1,2,3], [3,2,1], [2,1,3], [1,1,1]]) 

I want to return an array like this:

 [[[ 1 0 0] [ 0 1 0] [ 0 0 1]] [[ 0 0 1] [ 0 1 0] [ 1 0 0]] [[ 0 1 0] [ 1 0 0] [ 0 0 1]] [[ 1 0 0] [ 1 0 0] [ 1 0 0]]] 

Where the array tells me that 1 occurs once in the first position, 2 occurs once in the second position, 3 - once in the third position, 1 - once in the fourth position, etc. Later I will have more input arrays of the same sizes, and I would like to add values ​​to this counter array to the general values.

The code I have now is:

 a = np.array([[1,2,3], [3,2,1], [2,1,3], [1,1,1]]) cumulative = np.zeros((4,3,3)) for r in range(len(cumulative)): for c in range(len(cumulative[0])): cumulative[r, c, a[r,c]-1] +=1 

This gives me the result I want. However, I would like to condense the for loops on one line using the following line:

 cumulative[:, :, a[:, :]-1] +=1 

This line does not work, and I can not find anything on the Internet on how to perform this operation. Any suggestions?

+5
source share
3 answers

IIUC, you can use the broadcast:

 In [93]: ((a[:, None] - 1) == np.arange(3)[:, None]).swapaxes(2, 1).astype(int) Out[93]: array([[[1, 0, 0], [0, 1, 0], [0, 0, 1]], [[0, 0, 1], [0, 1, 0], [1, 0, 0]], [[0, 1, 0], [1, 0, 0], [0, 0, 1]], [[1, 0, 0], [1, 0, 0], [1, 0, 0]]]) 
+3
source

This is not technically single-line, but if you ignore the maximum line length of PEP 8 , then you can shorten it to two lines.

 a = np.array([[1,2,3], [3,2,1], [2,1,3], [1,1,1]]) out = np.zeros((a.shape[0], 1 + a.max() - a.min(), a.shape[1]), dtype=np.int8) out[np.repeat(np.arange(a.shape[0]), a.shape[1]), np.subtract( a, a.min())[:].flatten(), np.tile(np.arange(a.shape[1]), a.shape[0])] = 1 print(out) 

What are the exits;

 [[[1 0 0] [0 1 0] [0 0 1]] [[0 0 1] [0 1 0] [1 0 0]] [[0 1 0] [1 0 0] [0 0 1]] [[1 0 0] [1 0 0] [1 0 0]]] 

This is probably not the most profitable or elegant solution, and, unfortunately, does not scale to n dimensions, but I hope this (almost single-line) is enough for you.


This is pretty cool, so I’ll briefly describe how it works.

  • The output array is created by default with zeros by default, and the total length of the "hot vectors" is equal to the range of the input array (I assumed that this is what you wanted, given that there was no string for the value specified in your example).

  • np.tile and np.repeat are used with np.arange to create the first and last index arrays, i.e. the indices of each element in a .

  • An unusual indication is used to populate the index numbers of the matching number to 1.

+1
source
 np.concatenate((a==1,a==2,a==3),axis=1).reshape((4,3,3)).transpose(0,2,1) + 0 
+1
source

Source: https://habr.com/ru/post/1269641/


All Articles