给出一个数组arr = [10, 11, 12]
,我想计算一个元素可以从另一个元素中减去的所有方法。对于1xN
数组,所需的输出是NxN数组,其中output[i, j] = arr[i] - arr[j]
。我的方法是生成两个数字的所有可能配对,然后进行减法和整形。如下
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]]
这很好,我接下来要做的是将其概括为2d输入。本质上,我想完成的工作是给一个MxN
数组以输出一个MxNxN
数组,并针对每一层(深度)对每一行执行上述功能。
我试图将MxN
输入数组重塑为MxNx1
,然后像以前一样计算乘积。我的假设是,它在元素方面的行为与以前相同,但不幸的是,它在行为上没有。
我的第一个想法是初始化适当形状的输出并在行上循环并“手动”设置值,但是我希望采用矢量化方法。有谁知道我该如何在二维范围内完成这一工作而又不会循环数千行?
答案 0 :(得分:2)
这是一种通用的矢量化方法,可以在将输入数组重塑为彼此可广播的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)
要执行其他任何元素式ufunc
操作,只需将其替换为减法操作即可。
样品运行-
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)
在@ClimbingTheCurve's posted solution 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
答案 1 :(得分:1)
解决方案是为1d情况编写一个函数,然后泛化使用函数np.apply_along_axis()
,该函数带有一个函数,一个要应用的轴和一个输入数组。这完全符合预期。
我使用的代码:
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