【问题标题】:Access n-th dimension in python在python中访问第n维
【发布时间】:2018-01-09 18:43:38
【问题描述】:

我想要对多维 numpy 数组的某些部分进行易于阅读的访问。对于任何数组来说,访问第一个维度都很容易 (b[index])。另一方面,访问第六维度是“困难的”(尤其是阅读)。

b[:,:,:,:,:,index] #the next person to read the code will have to count the :

有没有更好的方法来做到这一点? 特别是有没有一种方法,在编写程序时不知道轴?

编辑: 索引维度不一定是最后一个维度

【问题讨论】:

    标签: python arrays numpy multidimensional-array indexing


    【解决方案1】:

    您可以使用np.take。 例如:

    b.take(index, axis=5)
    

    【讨论】:

    • 太棒了。 np.arange(2**6).reshape((2,2,2,2,2,2)).take(1, axis=5) 对 numpy 了解得越多,我就越喜欢它。
    【解决方案2】:

    如果你想要一个视图并且想要它快速你可以手动创建索引:

    arr[(slice(None), )*5 + (your_index, )]
    #                   ^---- This is equivalent to 5 colons: `:, :, :, :, :`
    

    这比np.take 快得多,并且只比使用:s 索引慢一点:

    import numpy as np
    
    arr = np.random.random((10, 10, 10, 10, 10, 10, 10))
    
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], arr.take(4, axis=5))
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], arr[(slice(None), )*5 + (4, )])
    %timeit arr.take(4, axis=5)
    # 18.6 ms ± 249 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    %timeit arr[(slice(None), )*5 + (4, )]
    # 2.72 µs ± 39.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    %timeit arr[:, :, :, :, :, 4]
    # 2.29 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    但可能不那么可读,所以如果你经常需要它,你可能应该把它放在一个有意义的名字的函数中:

    def index_axis(arr, index, axis):
        return arr[(slice(None), )*axis + (index, )]
    
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], index_axis(arr, 4, axis=5))
    
    %timeit index_axis(arr, 4, axis=5)
    # 3.79 µs ± 127 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    【讨论】:

    • 有趣。知道为什么它会比官方的np.take 更快吗?
    • @EricDuminil np.take 制作副本(慢),而普通索引返回视图(相当快)。
    • index 不需要副本时,您的手工版本是否更快,这是否正确? IE。 index 是连续的数字吗?
    • 我还没计时。至少差异会小很多。连续数字是什么意思?只有一个?!
    【解决方案3】:

    MSeifert 和 kazemakase 的答案之间的中间方式(在可读性和时间方面)是使用np.rollaxis

    np.rollaxis(b, axis=5)[index]
    

    测试解决方案:

    import numpy as np
    
    arr = np.random.random((10, 10, 10, 10, 10, 10, 10))
    
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], arr.take(4, axis=5))
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], arr[(slice(None), )*5 + (4, )])
    np.testing.assert_array_equal(arr[:,:,:,:,:,4], np.rollaxis(arr, 5)[4])
    
    %timeit arr.take(4, axis=5)
    # 100 loops, best of 3: 4.44 ms per loop
    %timeit arr[(slice(None), )*5 + (4, )]
    # 1000000 loops, best of 3: 731 ns per loop
    %timeit arr[:, :, :, :, :, 4]
    # 1000000 loops, best of 3: 540 ns per loop
    %timeit np.rollaxis(arr, 5)[4]
    # 100000 loops, best of 3: 3.41 µs per loop
    

    【讨论】:

      【解决方案4】:

      本着@Jürg Merlin Spaak 的rollaxis 的精神,但要快得多,而不是deprecated

      b.swapaxes(0, axis)[index]
      

      【讨论】:

        【解决方案5】:

        你可以说:

        slice = b[..., index]
        

        【讨论】:

        • 我想这只有在我想索引最后一个维度时才有效,对吧?
        • @JürgMerlinSpaak 啊,是的,我以为你指的是最后一个维度。如果你想要从前到最后的东西,你可以做b[..., index, :] 或类似的东西,但我猜np.take 会更清楚。
        猜你喜欢
        • 2018-12-25
        • 1970-01-01
        • 2018-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多