Search code examples
pythonnumpynumpy-ndarray

creating a 2D numpy array from the min of the i-th and j-th elements of a 1D array


Given a 1D array, I would like to create a 2D numpy array where the element at arr2d[i,j] is equal to min(arr1d[i], arr1d[j]).

I can achieve this with the code below:

arr1d = np.array([5, 4, 3, 4, 2, 3])
arr2d = np.zeros((arr1d.shape[0], arr1d.shape[0]))
for i in range(arr1d.shape[0]):
    for j in range(arr1d.shape[0]):
        arr2d[i, j] = min(arr1d[i], arr1d[j])

...but I feel like there should be a more idiomatic and/or efficient way to achieve this with numpy. Can anyone suggest a cleaner solution?


Solution

  • Imagine you repeated arr1d to make a square array. Then, arr2d is the elementwise minimum of that square array and its transpose (since that will compare i with j).

    a1 = np.repeat(arr1d[None,:], arr1d.shape[0], axis=0)
    a2 = a1.T
    arr2d = np.minimum(a1, a2)  # elementwise minimum
    

    Here is what a1 looks like:

    array([[5, 4, 3, 4, 2, 3],
           [5, 4, 3, 4, 2, 3],
           [5, 4, 3, 4, 2, 3],
           [5, 4, 3, 4, 2, 3],
           [5, 4, 3, 4, 2, 3],
           [5, 4, 3, 4, 2, 3]])
    

    And here's arr2d:

    array([[5, 4, 3, 4, 2, 3],
           [4, 4, 3, 4, 2, 3],
           [3, 3, 3, 3, 2, 3],
           [4, 4, 3, 4, 2, 3],
           [2, 2, 2, 2, 2, 2],
           [3, 3, 3, 3, 2, 3]])
    

    Or, without the intermediate arrays (as suggested in the comments):

    arr2d = np.minimum(arr1d, arr1d[:,None])