二维数组中每条对角线的最大值

jez*_*ael 9 python numpy max vectorization diagonal

我有数组,需要动态窗口的最大滚动差异。

a = np.array([8, 18, 5,15,12])
print (a)
[ 8 18  5 15 12]
Run Code Online (Sandbox Code Playgroud)

所以首先我自己创造差异:

b = a - a[:, None]
print (b)
[[  0  10  -3   7   4]
 [-10   0 -13  -3  -6]
 [  3  13   0  10   7]
 [ -7   3 -10   0  -3]
 [ -4   6  -7   3   0]]
Run Code Online (Sandbox Code Playgroud)

然后将上三角矩阵替换为 0:

c = np.tril(b)
print (c)
[[  0   0   0   0   0]
 [-10   0   0   0   0]
 [  3  13   0   0   0]
 [ -7   3 -10   0   0]
 [ -4   6  -7   3   0]]
Run Code Online (Sandbox Code Playgroud)

最后需要每个对角线的最大值,所以这意味着:

max([0,0,0,0,0]) = 0  
max([-10,13,-10,3]) = 13
max([3,3,-7]) = 3
max([-7,6]) = 6
max([-4]) = -4
Run Code Online (Sandbox Code Playgroud)

所以预期输出是:

[0, 13, 3, 6, -4]
Run Code Online (Sandbox Code Playgroud)

什么是好的矢量化解决方案?或者是否有可能以另一种方式获得预期输出?

jde*_*esa 2

考虑到所涉及的高级索引,不确定这到底有多有效,但这是实现这一目标的一种方法:

\n\n
import numpy as np\n\na = np.array([8, 18, 5, 15, 12])\nb = a[:, None] - a\n# Fill lower triangle with largest negative\nb[np.tril_indices(len(a))] = np.iinfo(b.dtype).min  # np.finfo for float\n# Put diagonals as rows\ns = b.strides[1]\ndiags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))\n# Get maximum from each row and add initial zero\nc = np.r_[0, diags.max(1)]\nprint(c)\n# [ 0 13  3  6 -4]\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

编辑:

\n\n

另一种替代方案(可能不是您想要的)就是使用 Numba,例如如下所示:

\n\n
import numpy as np\n\na = np.array([8, 18, 5, 15, 12])\nb = a[:, None] - a\n# Fill lower triangle with largest negative\nb[np.tril_indices(len(a))] = np.iinfo(b.dtype).min  # np.finfo for float\n# Put diagonals as rows\ns = b.strides[1]\ndiags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))\n# Get maximum from each row and add initial zero\nc = np.r_[0, diags.max(1)]\nprint(c)\n# [ 0 13  3  6 -4]\n
Run Code Online (Sandbox Code Playgroud)\n\n

将这些方法与原始方法进行比较:

\n\n
import numpy as np\nimport numba as nb\n\ndef max_window_diffs_jdehesa(a):\n    a = np.asarray(a)\n    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)\n    out = np.full_like(a, dtinf.min)\n    _pwise_diffs(a, out)\n    return out\n\n@nb.njit(parallel=True)\ndef _pwise_diffs(a, out):\n    out[0] = 0\n    for w in nb.prange(1, len(a)):\n        for i in range(len(a) - w):\n            out[w] = max(a[i] - a[i + w], out[w])\n\na = np.array([8, 18, 5, 15, 12])\nprint(max_window_diffs(a))\n# [ 0 13  3  6 -4]\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一个对于较小的数组可能会更好一些,但对于较大的数组则效果不佳。另一方面,Numba 在所有情况下都相当不错。

\n