2015-01-26 34 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方法隨着大小減小。