Numpy:按索引移动/插入矩阵数组

时间:2017-02-04 03:43:53

标签: python arrays numpy matrix

我有一个对象,我将一个大规模的for循环方法转换为一系列矢量化的numpy数组(大约快50倍)。现在我试图添加一个新方法,我需要处理一个numpy矩阵,然后根据矩阵内的数组索引“移位”子数组内容(即插入值)。我知道我可以通过for循环实现这一点,但我试图通过使用矢量数学来实现加速增益。

我想知道是否有快速有效的方法来完成以下任务:

import numpy as np

period = [1, 2, 3]

x = [1, 10, 100]
y = [.2, .4, .6]

z = np.outer(x,y)

print(z)

结果:

[[  0.2   0.4   0.6]
 [  2.    4.    6. ]
 [ 20.   40.   60. ]]

我想在z中移动行,将基于句点的零数添加为z中的行索引,基本上如下:

[[   0.0   0.2   0.4    0.6 ]
 [   0.0   0.0   2.0    4.0    6.0 ]
 [   0.0   0.0   0.0   20.0   40.0   60.0 ]]

最终,我想要对垂直/列轴(轴= 1)求和。我需要一个如下的最终数组:

[   0.0   0.2   2.4   24.6   46.0   60.0]

3 个答案:

答案 0 :(得分:2)

frames=[]
files = [...some list of files..]
for img_file in files:
    frame = cv2.imread(img_file, 1)
    frames.append[frame]

# and then later
for frame in frames:
    cv2.imshow('frame', frame)


# or by individual frame
     cv2.imshow('frame', frames[123])

是一个参差不齐的清单。我们可以使用viectorized数组魔术来构建它,至少不是普通的东西。

要解决这个问题,我们需要展平或填充此结构

[[   0.0   0.2   0.4    0.6 ]
 [   0.0   0.0   2.0    4.0    6.0 ]
 [   0.0   0.0   0.0   20.0   40.0   60.0 ]]

[[   0.0   0.2   0.4    0.6    0.0    0.0]
 [   0.0   0.0   2.0    4.0    6.0    0.0 ]
 [   0.0   0.0   0.0   20.0   40.0   60.0 ]]

[ 0.0 0.2 0.4 0.6 0.0 0.0 2.0 4.0 6.0 0.0 0.0 0.0 20.0 40.0 60.0 ] 让我们对平面数组的块进行求和,但是你需要一个跳过总和。我想我可以探索扁平转置。

我的第一个想法是,填充的数组看起来像对角线的,[。2,2,2,20]在对角线上,[.4,4,40]在下一个偏移处,等等。我知道sum.reduceat可以根据矩阵和偏移量构建矩阵,但我不认为sparse中存在这样的函数。它们一次只能处理一个偏移量。

但它看起来也像numpy可以产生的那种偏移。

让我们探讨一下:

stride_tricks

这是我们想要的那种转变,但方向是错误的;所以让我们翻转In [458]: as_strided =np.lib.index_tricks.as_strided In [459]: Z=np.pad(z,[[0,0],[3,3]],mode='constant') In [460]: Z Out[460]: array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6, 0. , 0. , 0. ], [ 0. , 0. , 0. , 2. , 4. , 6. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 20. , 40. , 60. , 0. , 0. , 0. ]]) In [461]: Z.strides Out[461]: (72, 8) # prod an offset with (72+8, 8) In [462]: as_strided(Z,shape=(3,6),strides=(80,8)) Out[462]: array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6], [ 0. , 0. , 2. , 4. , 6. , 0. ], [ 0. , 20. , 40. , 60. , 0. , 0. ]])

Z

泛化可以留给读者。

是否有任何速度优势未知。可能不适用于这个小案例,对于非常大的案例可能是肯定的。

这会清理填充并稍微向前移动

In [463]: Z1=Z[::-1,:].copy()
In [464]: as_strided(Z1,shape=(3,6),strides=(80,8))
Out[464]: 
array([[  0. ,   0. ,   0. ,  20. ,  40. ,  60. ],
       [  0. ,   0. ,   2. ,   4. ,   6. ,   0. ],
       [  0. ,   0.2,   0.4,   0.6,   0. ,   0. ]])
In [465]: as_strided(Z1,shape=(3,6),strides=(80,8)).sum(0)
Out[465]: array([  0. ,   0.2,   2.4,  24.6,  46. ,  60. ])

这忽略了In [497]: Z=np.pad(z,[[0,0],[1,4]],mode='constant') In [498]: Z.strides Out[498]: (64, 8) In [499]: as_strided(Z,shape=(3,6),strides=(64-8,8)) Out[499]: array([[ 0. , 0.2, 0.4, 0.6, 0. , 0. ], [ 0. , 0. , 2. , 4. , 6. , 0. ], [ 0. , 0. , 0. , 20. , 40. , 60. ]]) 的构建方式。如果外部产品是问题的核心,我可以尝试跨越1d z,并使用y来执行加权总和。

x

在此构造中,In [553]: x=np.array([1,10,100]); y=np.array([.2,.4,.6]) In [554]: z=np.concatenate(([0,0],y[::-1],[0,0,0])) In [555]: z Out[555]: array([ 0. , 0. , 0.6, 0.4, 0.2, 0. , 0. , 0. ]) In [556]: Z=as_strided(z,shape=(3,6), strides=(8,8)) In [557]: Z Out[557]: array([[ 0. , 0. , 0.6, 0.4, 0.2, 0. ], [ 0. , 0.6, 0.4, 0.2, 0. , 0. ], [ 0.6, 0.4, 0.2, 0. , 0. , 0. ]]) In [558]: np.dot(x,Z) Out[558]: array([ 60. , 46. , 24.6, 2.4, 0.2, 0. ]) Z上的视图,因此小于之前的z。但我确信Z在将其发送到已编译的代码时会复制。 dot可能会避免这种情况,在不扩展视图的情况下对视图进行编译迭代。处理非常大的数组时,这可能会有所不同。

结果相反,但很容易修复。我甚至可以在施工期间修理它。

答案 1 :(得分:1)

循环第一维可行:

a = np.array(
    [[0.2 ,  0.4 ,  0.6],
     [2.,    4.,    6. ],
     [20.,   40.,   60. ]])

​
s0, s1 = a.shape
res = np.zeros((s0, s0 + s1))
for i in range(s1):
    res[i, i + 1: i + s0 + 1] = a[i] 

>>> np.sum(res,axis=0)
array([  0. ,   0.2,   2.4,  24.6,  46. ,  60. ])

答案 2 :(得分:1)

您还可以先计算指数并立即指定:

a = np.array(
    [[0.2 ,  0.4 ,  0.6],
     [2.,    4.,    6. ],
     [20.,   40.,   60. ]])

s0, s1 = a.shape
rows = np.repeat(np.arange(s0), s1).reshape(a.shape)
cols = (np.add.outer(np.arange(0, s0), np.arange(s1)) + 1)
res = np.zeros((s0, s0 + s1))
res[rows, cols] = a
np.sum(res,axis=0)

>>> np.sum(res,axis=0)
array([  0. ,   0.2,   2.4,  24.6,  46. ,  60. ])