二维数组中每个对角线的最大值 [英] Max value per diagonal in 2d array

查看:216
本文介绍了二维数组中每个对角线的最大值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有数组,并且需要最大的动态窗口滚动差.

I have array and need max of rolling difference with dynamic window.

a = np.array([8, 18, 5,15,12])
print (a)
[ 8 18  5 15 12]

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

So first I create difference by itself:

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]]

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

Then replace upper triangle matrix to 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]]

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

Last need max values per diagonal, so it means:

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

所以预期的输出是:

[0, 13, 3, 6, -4]

什么是好的矢量化解决方案?还是有可能以其他方式获得预期的输出?

What is some nice vectorized solution? Or is possible some another way for expected output?

推荐答案

不确定考虑所涉及的高级索引编制的效率如何,但这是一种实现方法:

Not sure exactly how efficient this is considering the advanced indexing involved, but this is one way to do that:

import numpy as np

a = np.array([8, 18, 5, 15, 12])
b = a[:, None] - a
# Fill lower triangle with largest negative
b[np.tril_indices(len(a))] = np.iinfo(b.dtype).min  # np.finfo for float
# Put diagonals as rows
s = b.strides[1]
diags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))
# Get maximum from each row and add initial zero
c = np.r_[0, diags.max(1)]
print(c)
# [ 0 13  3  6 -4]



另一种选择(也许不是您想要的)只是使用Numba,例如:

Another alternative, which may not be what you were looking for though, is just using Numba, for example like this:

import numpy as np
import numba as nb

def max_window_diffs_jdehesa(a):
    a = np.asarray(a)
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    out = np.full_like(a, dtinf.min)
    _pwise_diffs(a, out)
    return out

@nb.njit(parallel=True)
def _pwise_diffs(a, out):
    out[0] = 0
    for w in nb.prange(1, len(a)):
        for i in range(len(a) - w):
            out[w] = max(a[i] - a[i + w], out[w])

a = np.array([8, 18, 5, 15, 12])
print(max_window_diffs(a))
# [ 0 13  3  6 -4]

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

Comparing these methods to the original:

import numpy as np
import numba as nb

def max_window_diffs_orig(a):
    a = np.asarray(a)
    b = a - a[:, None]
    out = np.zeros(len(a), b.dtype)
    out[-1] = b[-1, 0]
    for i in range(1, len(a) - 1):
        out[i] = np.diag(b, -i).max()
    return out

def max_window_diffs_jdehesa_np(a):
    a = np.asarray(a)
    b = a[:, None] - a
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    b[np.tril_indices(len(a))] = dtinf.min
    s = b.strides[1]
    diags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))
    return np.concatenate([[0], diags.max(1)])

def max_window_diffs_jdehesa_nb(a):
    a = np.asarray(a)
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    out = np.full_like(a, dtinf.min)
    _pwise_diffs(a, out)
    return out

@nb.njit(parallel=True)
def _pwise_diffs(a, out):
    out[0] = 0
    for w in nb.prange(1, len(a)):
        for i in range(len(a) - w):
            out[w] = max(a[i] - a[i + w], out[w])

np.random.seed(0)
a = np.random.randint(0, 100, size=100)
r = max_window_diffs_orig(a)
print((max_window_diffs_jdehesa_np(a) == r).all())
# True
print((max_window_diffs_jdehesa_nb(a) == r).all())
# True

%timeit max_window_diffs_orig(a)
# 348 µs ± 986 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit max_window_diffs_jdehesa_np(a)
# 91.7 µs ± 1.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit max_window_diffs_jdehesa_nb(a)
# 19.7 µs ± 88.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

np.random.seed(0)
a = np.random.randint(0, 100, size=10000)
%timeit max_window_diffs_orig(a)
# 651 ms ± 26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit max_window_diffs_jdehesa_np(a)
# 1.61 s ± 6.19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit max_window_diffs_jdehesa_nb(a)
# 22 ms ± 967 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

对于较小的数组,第一个可能会更好一些,但对于较大的数组则不能很好地工作.另一方面,Numba在所有情况下都非常好.

The first one may be a bit better for smaller arrays, but doesn't work well for bigger ones. Numba on the other hand is pretty good in all cases.

这篇关于二维数组中每个对角线的最大值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆