简体   繁体   English

如何计算2d中数组元素之间差异的所有组合?

[英]How to calculate all combinations of difference between array elements in 2d?

Given an array arr = [10, 11, 12] I want to calculate all the ways that one element can be subtracted from another. 给定一个数组arr = [10, 11, 12]我想计算一个元素可以从另一个元素中减去的所有方法。 For a 1xN array the desired output is a NxN array where output[i, j] = arr[i] - arr[j] . 对于1xN阵列,所需输出是NxN阵列,其中output[i, j] = arr[i] - arr[j] My approach was to generate all the possible pairings of two numbers, subtract, and reshape. 我的方法是生成两个数字的所有可能的配对,减去和重塑。 As follows 如下

opts = np.array(list(product(arr, arr)))
[[10 10] 
 [10 11]
 [10 12]
 [11 10]
 [11 11]
 [11 12]
 [12 10]
 [12 11]
 [12 12]]
 diffs = (opts[:, 0] - opts[:, 1]).reshape(len(arr), -1)
 [[ 0 -1 -2]
  [ 1  0 -1]
  [ 2  1  0]]

This works quite nicely, what I would like to do next is to generalize this to a 2d input. 这很好用,我接下来要做的是将它推广到2d输入。 Essentially what I would like to accomplish is given an MxN array to output an MxNxN array, and for each layer (depth-wise) perform the above functionality for each row. 基本上我想要完成的是给出一个MxN数组来输出一个MxNxN数组,并且对于每一层(深度方向),为每一行执行上述功能。

I attempted to reshape the MxN input array to be MxNx1 and then calculate the product as before. 我试图将MxN输入数组重新MxNx1MxNx1 ,然后像以前一样计算产品。 My assumption was that it would behave element-wise the same as before, unfortunately not. 我的假设是,它会像以前一样在元素方面表现,遗憾的是没有。

My first thought is to initialize an output of the appropriate shape and loop over the rows and set the values "manually" but I was hoping for a vectorized approach. 我的第一个想法是初始化适当形状的输出并循环遍历行并“手动”设置值,但我希望采用矢量化方法。 Does anyone know how I can accomplish this in 2 dimensions without looping over thousands of rows? 有没有人知道如何在不绕过数千行的情况下在2维中完成此操作?

Here's a generic vectorized way to cover both 1D and 2D cases leveraging broadcasting after reshaping the input array to broadcastable shpaes against each other - 这是一种通用的矢量化方式,涵盖了在将输入数组重新映射为可广播的shpaes之后利用broadcasting 1D和2D情况 -

def permute_axes_subtract(arr, axis):
    # Get array shape
    s = arr.shape

    # Get broadcastable shapes by introducing singleton dimensions
    s1 = np.insert(s,axis,1)
    s2 = np.insert(s,axis+1,1)

    # Perform subtraction after reshaping input array to 
    # broadcastable ones against each other
    return arr.reshape(s1) - arr.reshape(s2)

To perform any other elementwise ufunc operation, simply replace the subtraction operation with it. 要执行任何其他的elementwise ufunc操作,只需用它取代了减法运算。

Sample run - 样品运行 -

In [184]: arr = np.random.rand(3)

In [185]: permute_axes_subtract(arr, axis=0).shape
Out[185]: (3, 3)

In [186]: arr = np.random.rand(3,4)

In [187]: permute_axes_subtract(arr, axis=0).shape
Out[187]: (3, 3, 4)

In [188]: permute_axes_subtract(arr, axis=1).shape
Out[188]: (3, 4, 4)

Timings on @ClimbingTheCurve's posted solution func - permute_difference and the one posted in this one on large 2D arrays - @ ClimbingTheCurve上发布的解决方案func - permute_difference和在大型2D阵列上发布的解决方案 -

In [189]: arr = np.random.rand(100,100)

In [190]: %timeit permute_difference(arr, axis=0)
     ...: %timeit permute_axes_subtract(arr, axis=0)
1 loop, best of 3: 295 ms per loop
1000 loops, best of 3: 1.17 ms per loop

In [191]: %timeit permute_difference(arr, axis=1)
     ...: %timeit permute_axes_subtract(arr, axis=1)
1 loop, best of 3: 303 ms per loop
1000 loops, best of 3: 1.12 ms per loop

The solution is to write a function for the 1d case and in order to generalize use the function np.apply_along_axis() which takes a function, an axis to apply along, and an input array. 解决方案是为1d情况编写函数,并且为了概括使用函数np.apply_along_axis() ,该函数接受函数,应用轴和输入数组。 This works exactly as intended. 这完全符合预期。 The code I used: 我用过的代码:

from itertools import product

import numpy as np


def permute_difference(arr, axis=1):
    """
    applies the _permute_difference to a 2d array
    along the specified axis

    Parameters
    ----------
    arr numpy.array

    Returns
    -------
    numpy.array
        a 3d array, each 2d array the i^th along the depth
        contains the permuted difference of the i^th row
        in the input array
    """
    def _permute_difference(arr):
        """
        calculates all the differences between all combinations
        terms in the input array. output[i,j] = arr[i] - arr[j]
        for every combination if ij.

        Parameters
        ----------
        arr numpy.array
            a 1d input array

        Returns
        -------
        numpy.array
            a 2d array

        Examples
        --------
        arr = [10, 11, 12]

        diffs = [[ 0 -1 -2]
                [ 1  0 -1]
                [ 2  1  0]]
        """
        opts = np.array(list(product(arr, arr)))
        d = (opts[:, 0] - opts[:, 1]).reshape(len(arr), -1)
        return d

    if arr.ndim == 1:
        diffs = _permute_difference(arr)
    else:
        diffs = np.apply_along_axis(permute_difference, axis, arr)
    return diffs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM