Python numpy中四维矩阵中非对齐元素的插入
我正在使用numpy1.9和python2.7.5处理四维矩阵 我正在使用3个numpy数组Python numpy中四维矩阵中非对齐元素的插入,python,arrays,numpy,matrix,multidimensional-array,Python,Arrays,Numpy,Matrix,Multidimensional Array,我正在使用numpy1.9和python2.7.5处理四维矩阵 我正在使用3个numpy数组A,B,C(这是要组合的数组): 我想根据C在A中插入B中的所有元素 例如: c[0,0]=[1]=>必须在[0,0,1,:]之后插入B[0,0,1,:] c[0,1]=[1]=>必须在[0,1,1,:]之后插入B[0,1,1,:] c[1,0]=[1]=>必须在[1,0,1,:]之后插入B[1,0,1,:] c[1,1]=[1]=>A[1,1,1,:]之后必须插入B[1,1,1,:] 我问了同样的问
A
,B
,C
(这是要组合的数组):
我想根据C
在A
中插入B
中的所有元素例如:
c[0,0]=[1]=>必须在[0,0,1,:]之后插入B[0,0,1,:]
c[0,1]=[1]=>必须在[0,1,1,:]之后插入B[0,1,1,:]
c[1,0]=[1]=>必须在[1,0,1,:]之后插入B[1,0,1,:]
c[1,1]=[1]=>A[1,1,1,:]之后必须插入B[1,1,1,:]
>>> C = np.asarray(C)
>>> D = np.ones((2,2,5,3))
>>> idx = np.arange(len(C))
>>> D[idx, C[:, 0], C[:, 1]+1] = B[idx, C[:, 0], C[:, 1]]
>>> D
array([[[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 102., 103., 104.],
[ 1., 1., 1.]]],
[[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 96., 97., 98.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]]]])
您可以将阵列重塑为3d,并使用上一个问题中的解决方案:
def fn_4d(A,B,C, fn):
shape = list(A.shape)
A = A.reshape(-1,A.shape[-2], A.shape[-1])
B = B.reshape(-1,B.shape[-2], B.shape[-1])
C = np.array(C).reshape(-1)
A2 = fn(A,B,C)
shape[-2] += 1
A2 = A2.reshape(shape)
return A2
如果你的迭代解是
def iter_3d(A,B,C):
A_2 = np.zeros((A.shape[0], A.shape[1] + 1, A.shape[2]))
for j in xrange(np.size(C, 0)):
i = C[j]
A_2[j, :, :] = np.concatenate((A[j, 0:i + 1, :], [B[j, i, :]], A[j, i + 1:, :]))
return A_2
fn_4d(A, B, C, iter_3d)
这种重塑非常普遍,适用于从原始3d尺寸到以上的任何尺寸-只要插入件处于-2
尺寸
连接的另一种选择是:
A_2[j,:,:] = np.insert(A[j,...], i+1, B[j,i,:], axis=0)
但深入到insert
,可以看出它实际上是在做:
A_2[j,:i+1,:] = A[j,:i+1,:]
A_2[j,i+1,:] = B[j,i,:]
A_2[j,i+2:,:] = A[j,i+1:,:]
这些备选方案的时间安排大致相同
一次插入多行的三维解决方案实际上使用布尔掩码索引:
def insert_3d2(A,B,C):
mi = np.ravel_multi_index([np.arange(A.shape[0]), C], A.shape[:2])
bvals = np.take(B.reshape(-1, B.shape[-1]), mi, axis=0)
# result = np.insert(A.reshape(-1, A.shape[2]), mi + 1, bvals, axis=0)
# which does:
mi += np.arange(len(mi))
A1 = A.reshape(-1, A.shape[2])
shape = list(A1.shape)
shape[0] += len(mi)
A2 = np.empty(shape,dtype=A1.dtype)
mask = np.ones(shape[0], dtype=bool)
mask[mi] = False
A2[mask,:] = A1
A2[mi,:] = bvals
A2 = A2.reshape(A.shape[0], -1, A.shape[2])
return A2
也就是说,它构造一个布尔掩码来定义在新的空数组中放置a
行的位置。显然,索引不连续块的速度优势很小
这里是对掩模方法的重写,没有任何展平。它始终比任何其他版本都快。我一直在C
上进行迭代,因为这是查看该参数最清晰的方法。将枚举(C)循环替换为向量操作,类似于用于mi
和bvals
的向量操作,可以节省少量时间
def insert_3d3(A,B,C):
# without flattening
shape = list(A.shape)
shape[1] += 1
A2 = np.empty(shape, dtype=A.dtype)
mask = np.ones(shape, dtype=bool)
for j,i in enumerate(C):
mask[j,i+1,:] = False
A2[j,i+1,:] = B[j,i,:]
A2[mask] = A.ravel()
return A2
我想你误解了,我所指的矩阵是示例(现在我编辑我的问题是为了澄清它),我想在A中插入B中的所有元素,根据C,但A是一个通用矩阵,而不是一个一个矩阵。那么我恐怕你的问题是严重定义不清的。。。为了能够插入这些条目,您需要将A
的形状扩展到第三维的1
。在2D切片中,A[0,1]
和A[1,0]
这很好,因为我们有东西要插入。但是应该在片A[0,0]
和A[1,1]
中插入什么?对不起,你完全正确。现在我更正我的问题,在3D情况下,for循环解决方案有什么问题?当然你可以扩展它。当然它会工作,但是for循环比纯numpy解决方案慢得多,我需要一个尽可能快的解决方案。你用3d insert解决方案计时了吗?对于这些小样本阵列,速度较慢。您使用的阵列的大小。最重要的是,C
中有多少术语?您了解3d insert解决方案吗?我对numpy
并不陌生,但我还是需要一些时间来消化它。我用(200200)
大小数组尝试了3d解决方案。您的迭代解决方案仍然快了3倍多。
def insert_3d3(A,B,C):
# without flattening
shape = list(A.shape)
shape[1] += 1
A2 = np.empty(shape, dtype=A.dtype)
mask = np.ones(shape, dtype=bool)
for j,i in enumerate(C):
mask[j,i+1,:] = False
A2[j,i+1,:] = B[j,i,:]
A2[mask] = A.ravel()
return A2