我在numpy中有两组3D点,我想创建一个矩阵和点的矢量表示,如下所示:
| X1 Y1 Z1 0 0 0 0 0 0 1 0 0| | X1 |
| 0 0 0 X1 Y1 Z1 0 0 0 0 1 0| | Y1 |
| 0 0 0 0 0 0 X1 Y1 Z1 0 0 1| | Z1 |
| X2 Y2 Z2 0 0 0 0 0 0 1 0 0| | X2 |
| 0 0 0 X2 Y2 Z2 0 0 0 0 1 0| | Y2 |
| 0 0 0 0 0 0 X2 Y2 Z2 0 0 1| | Z2 |
用法类似于:
import numpy as np
pts = np.random.rand(10, 3)
因此,矩阵现在的形状为(30, 12).
30行(每点3个)和12列。在这种情况下,矩阵长度为30个元素。有没有办法在python中实现这一点而不编写明确的for
循环?
答案 0 :(得分:4)
Kronecker product(np.kron
)对于构建这样的块矩阵非常有用:
import numpy as np
pts = np.arange(1, 31).reshape(10, 3)
n, d = pts.shape
I = np.eye(d, dtype=pts.dtype)
# the first d**2 columns of xyz values
xyzcols = np.kron(I, pts[:, None]).reshape(-1, d * d)
# the final d columns of ones
eyecols = np.tile(I, n).T
# concatenate
out = np.hstack([xyzcols, eyecols])
print(repr(out[:6]))
# array([[1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0],
# [0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 1, 0],
# [0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 1],
# [4, 5, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0],
# [0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 1, 0],
# [0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 1]])
答案 1 :(得分:3)
一种滥用linear indexing
和广播索引的矢量化方法 -
m,n = pts.shape
idx1 = np.arange(n)[:,None] + np.arange(n)*(n*(n+2))
idx2 = idx1 + np.arange(m)[:,None,None]*(n*n*(n+1))
idx3 = (n*n + np.arange(n)*(n*(n+1)+1)) + np.arange(m)[:,None]*(n*n*(n+1))
out = np.zeros((m*n,n*(n+1)),dtype=pts.dtype)
out.ravel()[idx2] = pts[:,:,None]
out.ravel()[idx3] = 1
示例运行 -
In [550]: pts
Out[550]:
array([[47, 34],
[36, 25],
[29, 38],
[35, 20],
[37, 48]])
In [551]: m,n = pts.shape
...:
...: idx1 = np.arange(n)[:,None] + np.arange(n)*(n*(n+2))
...: idx2 = idx1 + np.arange(m)[:,None,None]*(n*n*(n+1))
...: idx3=(n*n + np.arange(n)*(n*(n+1)+1)) + np.arange(m)[:,None]*(n*n*(n+1))
...:
...: out = np.zeros((m*n,n*(n+1)),dtype=pts.dtype)
...: out.ravel()[idx2] = pts[:,:,None]
...: out.ravel()[idx3] = 1
...:
In [552]: out
Out[552]:
array([[47, 34, 0, 0, 1, 0],
[ 0, 0, 47, 34, 0, 1],
[36, 25, 0, 0, 1, 0],
[ 0, 0, 36, 25, 0, 1],
[29, 38, 0, 0, 1, 0],
[ 0, 0, 29, 38, 0, 1],
[35, 20, 0, 0, 1, 0],
[ 0, 0, 35, 20, 0, 1],
[37, 48, 0, 0, 1, 0],
[ 0, 0, 37, 48, 0, 1]])