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)
什么是好的矢量化解决方案?或者是否有可能以另一种方式获得预期输出?
考虑到所涉及的高级索引,不确定这到底有多有效,但这是实现这一目标的一种方法:
\n\nimport 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]\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:
\n\n另一种替代方案(可能不是您想要的)就是使用 Numba,例如如下所示:
\n\nimport 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]\nRun Code Online (Sandbox Code Playgroud)\n\n将这些方法与原始方法进行比较:
\n\nimport 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]\nRun Code Online (Sandbox Code Playgroud)\n\n第一个对于较小的数组可能会更好一些,但对于较大的数组则效果不佳。另一方面,Numba 在所有情况下都相当不错。
\n