Suppose I have the following arrays:
first_array = array([[1, 8, 3, 9, 2], [2, 6, 4, 1, 9], [4, 2, 12, 8, 16], [5, 3, 7, 18, 21], [6, 20, 4, 8, 24]])
So an array with shape (5, 5)
Now I have a second array, which is a slice of the first:
second_array = array([[1, 8, 3, 9, 2], [2, 6, 4, 1, 9]])
An array with shape (2, 5)
.
Now I want to subtract every vector of the first array by the vectors of the second array subsequently(excluding- in the first array- the vector of the second array I’m using to subtract), element-wise. I want to this for every vector of the second array.
So I want to have as an output:
subtracted_array = array([[[1, -2, 1, -8, 7], [3, -6, 9, -1, 14], [4, -5, 4, 9, 19], [5, 12, 1, -1, 22]], [[-1, 2, -1, 8, -7], [2, -4, 8, 7, 7], [3, -3, 3, 17, 12], [4, 14, 0, 7, 15]]])
So this is an array with shape (2, 4, 5)
How do we do this with broadcasting?
Advertisement
Answer
Does this code do what you meant you needed done?
You are welcomed to test it on your test case and update me if you need more help.
import numpy as np arr = np.arange(50).reshape(10, 5) arr_slice = arr[:2, :] # "outer" tensor subtraction arr_sub = arr_slice[:, None, :] - arr[None, :, :] # create an index map of the vector combinations idx0, idx1 = np.mgrid[:2, :10] idx0, idx1 = idx0.flatten(), idx1.flatten() # find the irrelevent combinations and remove them remove_same = (1 - (idx0 == idx1)).astype(bool) idx0, idx1 = idx0[remove_same], idx1[remove_same] arr_sub = arr_sub[idx0, idx1, :].reshape(2, 9, 5)
EDIT: here’s a more efficient method:
import numpy as np arr = np.arange(50).reshape(10, 5) arr_slice = arr[:2, :] # create an index map of the vector combinations idx0, idx1 = np.mgrid[:2, :10] idx0, idx1 = idx0.flatten(), idx1.flatten() # find the irrelevent combinations and remove them remove_same = (1 - (idx0 == idx1)).astype(bool) idx0, idx1 = idx0[remove_same], idx1[remove_same] arr_sub = arr_slice[idx0, :] - arr[idx1, :] arr_sub = arr_sub.reshape(2, 9, 5)
output:
arr = [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19] [20 21 22 23 24] [25 26 27 28 29] [30 31 32 33 34] [35 36 37 38 39] [40 41 42 43 44] [45 46 47 48 49]] arr_slice = [[0 1 2 3 4] [5 6 7 8 9]] arr_sub = [[[ -5 -5 -5 -5 -5] [-10 -10 -10 -10 -10] [-15 -15 -15 -15 -15] [-20 -20 -20 -20 -20] [-25 -25 -25 -25 -25] [-30 -30 -30 -30 -30] [-35 -35 -35 -35 -35] [-40 -40 -40 -40 -40] [-45 -45 -45 -45 -45]] [[ 5 5 5 5 5] [ -5 -5 -5 -5 -5] [-10 -10 -10 -10 -10] [-15 -15 -15 -15 -15] [-20 -20 -20 -20 -20] [-25 -25 -25 -25 -25] [-30 -30 -30 -30 -30] [-35 -35 -35 -35 -35] [-40 -40 -40 -40 -40]]]
EDIT 2: I subtracted the arrays in the wrong order (the whole array from the slice instead of the other way around). So here’s a fix and this time I’m using your example:
import numpy as np first_array = np.array( [[1, 8, 3, 9, 2], [2, 6, 4, 1, 9], [4, 2, 12, 8, 16], [5, 3, 7, 18, 21], [6, 20, 4, 8, 24]] ) arr_slice = slice(None, 2) second_array = first_array[arr_slice] expected_subtracted_array = np.array( [[[[1, -2, 1, -8, 7], [3, -6, 9, -1, 14], [4, -5, 4, 9, 19], [5, 12, 1, -1, 22]], [[-1, 2, -1, 8, -7], [2, -4, 8, 7, 7], [3, -3, 3, 17, 12], [4, 14, 0, 7, 15]]]] ) # create an index map of the vector combinations idx0, idx1 = np.mgrid[:second_array.shape[0], :first_array.shape[0]] idx0, idx1 = idx0.flatten(), idx1.flatten() # find the irrelevent combinations and remove them remove_same = (1 - (idx0 == idx1)).astype(bool) idx0, idx1 = idx0[remove_same], idx1[remove_same] arr_sub = first_array[idx1, :] - second_array[idx0, :] arr_sub = arr_sub.reshape(second_array.shape[0], first_array.shape[0]-1, first_array.shape[1]) (arr_sub == expected_subtracted_array).all()
Output:
True