2015-01-26 60 views
0

我无法找到任何有关我想做什么的问题,所以我现在问。基本上,我想在行索引取决于列索引的矩阵中切片。Numpy:依赖于列的切片

例如:

>>> import numpy as np 
>>> x = np.arange(24).reshape(6,4) 
>>> x 
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]]) 

现在我需要的是:

array([[12, 9, 6, 3], 
     [16, 13, 10, 7], 
     [20, 17, 14, 11]]) 

所以我列索引的给定的(固定)集。行索引取决于它们。例如:row = col-1:col+1

有没有一种有效的方法来做到这一点?我知道我可以对每一列中需要的条目进行迭代和切片,但对我来说这似乎效率很低。

+0

你可以用'np.diag'和'np.rot90'或者'np.transpose'的组合来建立它。留下这作为评论,因为我不知道如何做你要求的确切提取。 – mtrw 2015-01-26 19:14:03

+0

对角线解决方案:'np.array([x [:: - 1,:]。对角线(i)对于[-2,-1,0]])'中的i。它确实涉及在输出的每一行上进行交互,因为'np.diagonal'不需要列表。 – hpaulj 2015-01-27 01:07:16

回答

4

您可以使用as_strided做到这一点:

In [1]: from numpy.lib.stride_tricks import as_strided 
In [2]: sz = x.itemsize 
In [3]: d = as_strided(x[-1::-1,:], shape=(3,4), strides=sz*np.array([-4,-3])) 
In [4]: d 
Out[5]: 
array([[20, 17, 14, 11], 
     [16, 13, 10, 7], 
     [12, 9, 6, 3]]) 

也就是说,从原来的阵列倒置,填补了3x4的阵列与大踏步倒退4项为第一坐标和3所项目第二。

如果你愿意,你就可以查看d颠倒:

In [6]: d[-1::-1,:] # or np.flipud(d) 
Out[6]: 
array([[12, 9, 6, 3], 
     [16, 13, 10, 7], 
     [20, 17, 14, 11]]) 
2

我要在评论中留下一个diagonal基础的解决方案,但在时间测试中,它被证明是比strided一个快。

In [128]: timeit d = as_strided(x[::-1,:], shape=(3,4), 
    strides=sz*np.array([-4,-3]))[::-1,:] 
10000 loops, best of 3: 44 µs per loop 

In [129]: timeit np.array([x[::-1,:].diagonal(i) for i in [-2,-1,0]]) 
10000 loops, best of 3: 25.9 µs per loop 

随着一个较大的x这可能不会成立。但是diagonal解决方案具有可能更易于理解的优点。


用于(69,40)x

np.array([x[::-1,:].diagonal(i) for i in range(-(n-1),1)]) 

产生(30,40)阵列,其包括所有的长度40的反向对角线。

as_strided的解决方案是:

as_strided(x[::-1,:], shape=(n,m), strides=-sz*np.array([m,m-1]))[::-1,:] 

这是不容易弄清楚如何调整值以产生正确的步伐。但速度更快。时间基本上与较小阵列相同,而diagonal方法随着大小减小。