2015-11-06 3 views
4

У меня есть два комплекта 3D очков в NumPy, и я хотел бы создать матрицу и вектор представление точек следующим образом:Создание этого блока матрицы в NumPy

| 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?

ответ

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]]) 
+0

Спасибо. Использование кронекерских продуктов было откровением. – Luca

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]]) 
Смежные вопросы