【问题标题】:getting the opposite diagonal of a numpy array获取numpy数组的对角线
【发布时间】:2013-04-19 22:21:36
【问题描述】:

所以在 numpy 数组中有用于获取对角线索引的内置函数,但我似乎无法弄清楚如何从右上角而不是左上角开始获取对角线。

这是从左上角开始的正常代码:

>>> import numpy as np
>>> array = np.arange(25).reshape(5,5)
>>> diagonal = np.diag_indices(5)
>>> array
array([[ 0,  1,  2,  3,  4],
   [ 5,  6,  7,  8,  9],
   [10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19],
   [20, 21, 22, 23, 24]])
>>> array[diagonal]
array([ 0,  6, 12, 18, 24])

如果我想让它返回,我该怎么做:

array([ 4,  8, 12, 16, 20])

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    In [47]: np.diag(np.fliplr(array))
    Out[47]: array([ 4,  8, 12, 16, 20])
    

    In [48]: np.diag(np.rot90(array))
    Out[48]: array([ 4,  8, 12, 16, 20])
    

    在两者中,np.diag(np.fliplr(array)) 更快:

    In [50]: %timeit np.diag(np.fliplr(array))
    100000 loops, best of 3: 4.29 us per loop
    
    In [51]: %timeit np.diag(np.rot90(array))
    100000 loops, best of 3: 6.09 us per loop
    

    【讨论】:

    • 你开始计时了,所以这是我加快速度的最佳方法:step = len(array) - 1; np.take(array, np.arange(step, array.size, step))
    • @Jaime:太好了——比我的解决方案快得多。也许我们需要np.arange(step, array.size-1, step)?请将其发布为解决方案,以便我投票。
    • 我的立方体墙上挂着 Tim Peters 的 The Zen of Python,就在我的显示器旁边。当 readability counts 正在看着我时,我无法将评论的代码作为答案发布...:P 您使用 fliplr 的解决方案可能是最好的:足够快,并且在以下情况下更容易理解你在写完它几个月后重新审视它。
    • @Jaime 你总是会对这些时间感到松懈,因为对角线会创建一个视图(或在较新的版本中)。
    • @Jaime - 我对我的解决方案的 zen-iness 没有疑虑:np.diag(arr[:, ::-1] ;) - 请参阅下面的答案!
    【解决方案2】:

    这里有两个想法:

    step = len(array) - 1
    
    # This will make a copy
    array.flat[step:-step:step]
    
    # This will make a veiw
    array.ravel()[step:-step:step]
    

    【讨论】:

    • 第二个可能会复制 ;)
    【解决方案3】:

    这是一个使用 numpy 切片的简单方法。我个人觉得这并不难看(但承认fliplr 更具描述性!)。

    为了突出这个示例对现有答案的贡献,我运行了相同的简单基准测试。

    In [1]: import numpy as np
    
    In [3]: X = np.random.randint(0, 10, (5, 5))
    
    In [4]: X
    Out[4]: 
    array([[7, 2, 7, 3, 7],
           [8, 4, 5, 9, 6],
           [0, 2, 9, 0, 4],
           [8, 2, 1, 0, 3],
           [3, 1, 0, 7, 0]])
    
    In [5]: Y = X[:, ::-1]
    
    In [6]: Z1 = np.diag(Y)
    
    In [7]: Z1
    Out[7]: array([7, 9, 9, 2, 3])
    

    现在与给出的当前最快解决方案进行比较。

    In [8]: step = len(X) - 1
    
    In [9]: Z2 = np.take(X, np.arange(step, X.size-1, step))
    
    In [10]: Z2
    Out[10]: array([7, 9, 9, 2, 3])
    
    In [11]: np.array_equal(Z1, Z2)
    Out[11]: True
    

    基准测试

    In [12]: %timeit np.diag(X[:, ::-1])
    1.92 µs ± 29.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    
    In [13]: %timeit step = len(X) - 1; np.take(X, np.arange(step, X.size-1, step))
    2.21 µs ± 246 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    初步比较表明,我的解决方案在复杂性上也是线性的,而使用第二个“步骤”解决方案则不是:

    In [14]: big_X = np.random.randint(0, 10, (10000, 10000))
    
    In [15]: %timeit np.diag(big_X[:, ::-1])
    2.15 µs ± 96.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    
    In [16]: %timeit step = len(big_X) - 1; np.take(big_X, np.arange(step, big_X.size-1, step))
    100 µs ± 1.85 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    我通常使用这种方法来翻转图像(镜像它们),或者在opencv的格式(通道,高度,宽度)matplotlib的格式之间转换(高度、宽度、通道)。所以对于一个三维图像,它只是flipped = image[:, :, ::-1]。当然,您可以通过将::-1 部分放在所需的维度中,将其概括为沿任何维度翻转。

    【讨论】:

      猜你喜欢
      • 2015-05-09
      • 2022-01-26
      • 2012-06-05
      • 2019-09-20
      • 1970-01-01
      • 2011-05-25
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多