我使用 numpy 1.9 和 python 2.7.5 处理4维矩阵。
我正在使用3个numpy数组A
,B
,C
(这是要简化的数组):
>>> A = np.ones((2,2,4,3));
>>> B = np.ones((2,2,4,3))*-1; B[0,0,1,:] = [10,11,12]; B[0,1,1,:] = [13,14,15]; B[1,0,1,:] = [16,17,18]; B[1,1,1,:] = [19,20,21];
>>> C = [[1,1],[1,1]]
根据A
,我希望在B
中插入C
的所有元素。
例如:
c[0,0] = [1] => After A[0, 0, 1, :] has to be inserted B[0, 0, 1, :]
c[0,1] = [1] => After A[0, 1, 1, :] has to be inserted B[0, 1, 1, :]
c[1,0] = [1] => After A[1, 0, 1, :] has to be inserted B[1, 0, 1, :]
c[1,1] = [1] => After A[1, 1, 1, :] has to be inserted B[1, 1, 1, :]
我为3D数组问了同样的问题here,但是对于4D数组我得不到相同的结果(我对numpy来说很新)。
有什么想法吗?
谢谢!
答案 0 :(得分: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)
这种重塑非常普遍,只要插入位于-2
维度,就可以处理原始3d大小的任何内容。
concatenate
的替代方法是:
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:,:]
这些替代方案的时间安排大致相同。
一次插入多行{3}}的3d解决方案实际上使用了布尔掩码索引:
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
以上,因为这是查看该参数的最清晰方式。使用与mi
和bvals
类似的向量运算替换枚举(C)循环可以节省很少的时间。
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
答案 1 :(得分:0)
>>> 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.]]]])