Numpy Array and axis - python

I have an array A which has the shape (2, n) and second array B with the shape (n, 2) and I want to create an array C with the shape (n, 2, 2) by multiplying axis=0 of the first array A and axis=1 of the second array B to receive 10 "arrays" of the shape (2, 2) which are stored in the array C
I dont know how to do this... hope someone can help, thanks in advance!
Here some test data with n=10:
A = [array([1, 2, 3, 4, 4, 4, 4, 4, 4, 2]), array([2, 3, 2, 4, 3, 6, 8, 5, 2, 1])]
B = [array([1, 2]), array([3, 2]), array([1, 1]), array([2, 2]), array([6, 1]), array([4, 5]), array([1, 2]), array([1, 2]), array([1, 2]), array([1, 2])]

You can use moveaxis to change the array shapes to line up, then insert additional axes as necessary:
C = np.moveaxis(A, 1, 0)[..., None] * B[:, None, ...]
Another way would be to apply it after the multiplication, but that would run the risk of creating a non-contiguous memory layout, and is therefore generally less desirable:
C = np.moveaxis(A[..., None] * B[None, ...], 1, 0)
Similar results can be achieved with transpose and swapaxes.

Related

Numpy: for each element in one dimension, find coordinates of maximum of sub-array

I've seen variations of this question asked a few times but so far haven't seen any answers that get to the heart of this general case. I have an n-dimensional array of shape [a, b, c, ...] . For some dimension x, I want to look at each sub-array and find the coordinates of the maximum.
For example, say b = 2, and that's the dimension I'm interested in. I want the coordinates of the maximum of [:, 0, :, ...] and [:, 1, :, ...] in the form a_max = [a_max_b0, a_max_b1], c_max = [c_max_b0, c_max_b1], etc.
I've tried to do this by reshaping my input matrix to a 2d array [b, a*c*d*...], using argmax along axis 0, and unraveling the indices, but the output coordinates don't wind up giving the maxima in my dataset. In this case, n = 3 and I'm interested in axis 1.
shape = gains_3d.shape
idx = gains_3d.reshape(shape[1], -1)
idx = idx.argmax(axis = 1)
a1, a2 = np.unravel_index(idx, [shape[0], shape[2]])
Obviously I could use a loop, but that's not very pythonic.
For a concrete example, I randomly generated a 4x2x3 array. I'm interested in axis 1, so the output should be two arrays of length 2.
testarray = np.array([[[0.17028444, 0.38504759, 0.64852725],
[0.8344524 , 0.54964746, 0.86628204]],
[[0.77089997, 0.25876277, 0.45092835],
[0.6119848 , 0.10096425, 0.627054 ]],
[[0.8466859 , 0.82011746, 0.51123959],
[0.26681694, 0.12952723, 0.94956865]],
[[0.28123628, 0.30465068, 0.29498136],
[0.6624998 , 0.42748154, 0.83362323]]])
testarray[:,0,:] is
array([[0.17028444, 0.38504759, 0.64852725],
[0.77089997, 0.25876277, 0.45092835],
[0.8466859 , 0.82011746, 0.51123959],
[0.28123628, 0.30465068, 0.29498136]])
, so the first element of the first output array will be 2, and the first element of the other will be 0, pointing to 0.8466859. The second elements of the two matrices will be 2 and 2, pointing to 0.94956865 of testarray[:,1,:]
Let's first try to get a clear idea of what you are trying to do:
Sample 3d array:
In [136]: arr = np.random.randint(0,10,(2,3,4))
In [137]: arr
Out[137]:
array([[[1, 7, 6, 2],
[1, 5, 7, 1],
[2, 2, 5, *6*]],
[[*9*, 1, 2, 9],
[2, *9*, 3, 9],
[0, 2, 0, 6]]])
After fiddling around a bit I came up with this iteration, showing the coordinates for each middle dimension, and the max value
In [151]: [(i,np.unravel_index(np.argmax(arr[:,i,:]),(2,4)),np.max(arr[:,i,:])) for i in range
...: (3)]
Out[151]: [(0, (1, 0), 9), (1, (1, 1), 9), (2, (0, 3), 6)]
I can move the unravel outside the iteration:
In [153]: np.unravel_index([np.argmax(arr[:,i,:]) for i in range(3)],(2,4))
Out[153]: (array([1, 1, 0]), array([0, 1, 3]))
Your reshape approach does avoid this loop:
In [154]: arr1 = arr.transpose(1,0,2) # move our axis first
In [155]: arr1 = arr1.reshape(3,-1)
In [156]: arr1
Out[156]:
array([[1, 7, 6, 2, 9, 1, 2, 9],
[1, 5, 7, 1, 2, 9, 3, 9],
[2, 2, 5, 6, 0, 2, 0, 6]])
In [158]: np.argmax(arr1,axis=1)
Out[158]: array([4, 5, 3])
In [159]: np.unravel_index(_,(2,4))
Out[159]: (array([1, 1, 0]), array([0, 1, 3]))
max and argmax take only one axis value, where as you want the equivalent of taking the max along all but one axis. Some ufunc takes a axis tuple, but these do not. The transpose and reshape may be the only way.
In [163]: np.max(arr1,axis=1)
Out[163]: array([9, 9, 6])

How to extract tensors to numpy arrays or lists from a larger pytorch tensor

I have a list of pytorch tensors as shown below:
data = [[tensor([0, 0, 0]), tensor([1, 2, 3])],
[tensor([0, 0, 0]), tensor([4, 5, 6])]]
Now this is just a sample data, the actual one is quite large but the structure is similar.
Question: I want to extract the tensor([1, 2, 3]), tensor([4, 5, 6]) i.e., the index 1 tensors from data to either a numpy array or a list in flattened form.
Expected Output:
out = array([1, 2, 3, 4, 5, 6])
OR
out = [1, 2, 3, 4, 5, 6]
I have tried several ways one including map function like:
map(lambda x: x[1].numpy(), data)
This gives:
[array([1, 2, 3]),
array([4, 5, 6])]
And I'm unable to get the desired result with any other method I'm using.
OK, you can just do this.
out = np.concatenate(list(map(lambda x: x[1].numpy(), data)))
You can convert a nested list of tensors to a tensor/numpy array with a nested stack:
data = np.stack([np.stack([d for d in d_]) for d_ in data])
You can then easily index this, and concatenate the output:
>>> np.concatenate(data[:,1])
array([[1, 2, 3],
[4, 5, 6]])

Python, How can I stack a 2D array into a 3D array

Now,i have a 3D(c) array and a 2D(b) array,i want to make a new 3D(d) array, so what shall I do? :
c=np.array([[[1, 2, 3],[2, 3, 4]],[[1, 2, 3],[2, 3, 4]]])
c.shape
(2, 2, 3)
a=np.array([[1, 2, 3],[2, 3, 4]])
a.shape
(2, 3)
d=np.array([[[1, 2, 3],[2, 3, 4]],[[1, 2, 3],[2, 3, 4]],[[1,2,3],[1,2,3]]])
d.shape
(3, 2, 3)
You first need to reshape one of them, then you can use vstack or dstack depends on which one you want to use. For example I use dstack:
c = c.reshape((2, 3, 2))
np.dstack((c, a)).shape
i solved it.
b.reshape(1,2,3), then d=np.vstack((c,b))

Splitting Numpy arrays based on its elements, where each element of the array is unique

I have a Numpy 1D vector, for example x = [1, 1, 1, 2, 2, 1, 3, 3, 1]
I have to perform a splitting of it into n subarrays, where each vector must start with a new value and continue for as long as the value is the same, such that the final answer is [[1, 1, 1], [2, 2], [1], [3, 3], [1]].
I do understand that I have to use numpy.split() function, but I have problems with finding the places at which the splitting must be done.
I humbly ask of your help, thanks for your time!
You just need to give numpy.split the indexes you need it to split the array
a = np.array([1,1,1,2,2,1,3,3,1])
np.split(a, np.argwhere(np.diff(a) != 0)[:,0] + 1)
# [array([1, 1, 1]), array([2, 2]), array([1]), array([3, 3]), array([1])]
Details
Using np.diff(a) you get the differences between each consecutive element
np.diff(a)
# array([ 0, 0, 1, 0, -1, 2, 0, -2])
The points where the differences are not equal to 0 is the points where the elements are not consecutively the same. Since you are looking for the indexes where the changes you need to do np.diff(a) != 0 which returns:
np.diff(a) != 0
# array([False, False, True, False, True, True, False, True])
To convert the booleans into the indexes you can use np.argwhere
np.argwhere(np.diff(a) != 0)
# array([[2],[4],[5],[7]])
# since we only need this for 1d arrays
np.argwhere(np.diff(a) != 0)[:,0]
# array([2, 4, 5, 7])
The you just use the aforementioned procedure to provide the correct indexes to np.split
np.split(a, np.argwhere(np.diff(a) != 0)[:,0])
# [array([1, 1]), array([1, 2]), array([2]), array([1, 3]), array([3, 1])]
Woops... wrong indexes... Seems we are off by 1 index. No problem, just add +1 to the results of np.argwhere
np.split(a, np.argwhere(np.diff(a) != 0)[:,0] + 1)
# [array([1, 1, 1]), array([2, 2]), array([1]), array([3, 3]), array([1])]

numpy append to an indexed array (after np.where)

I want to append values to a selection of array without having to go through a for loop.
i.e. if I want to add 0 values to certain locations of an array:
a=np.array([[1,2,3,4,5],[1,2,3,4,5]])
condition=np.where(a>2)
a[condition]=np.append(a[condition],np.array([0]*len(condition[0])))
-> ValueError: shape mismatch: value array of shape (12,) could not be broadcast to indexing result of shape (6,)
Edit for clarification:
I need to add values (and dimension if needed) to selected array location. The loop looks like that:
for t in range(len(ind)):
c = cols[t]
r = rows[t]
if data1[r, c] > 2:
data2[r,c]=np.append(data2[r,c],t)
Is there any way to remove this loop (~100 000 iterations)? Thank
Let's look at the pieces:
In [92]: a=np.array([[1,2,3,4,5],[1,2,3,4,5]])
...: condition=np.where(a>2)
...:
In [93]: a
Out[93]:
array([[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]])
In [94]: condition
Out[94]:
(array([0, 0, 0, 1, 1, 1], dtype=int32),
array([2, 3, 4, 2, 3, 4], dtype=int32))
In [95]: a[condition]
Out[95]: array([3, 4, 5, 3, 4, 5])
In [96]: np.append(a[condition],np.array([0]*len(condition[0])))
Out[96]: array([3, 4, 5, 3, 4, 5, 0, 0, 0, 0, 0, 0])
You are trying to put 12 values into 6 slots. No can do!
What are you expecting? I don't think I should even speculate. Go ahead show us the loop.

Categories

Resources