np.vectorize
будет в основном l oop под капотами. Мы могли бы использовать NumPy funcs для фактической векторизации на уровне Python. Вот один из таких способов -
def blockwise_jordan(a):
r = a[:,1].astype(int)
v = np.repeat(a[:,0],r)
out = np.diag(v)
n = out.shape[1]
fillvals = np.ones(n, dtype=out.dtype)
fillvals[r[:-1].cumsum()-1] = 0
out.flat[1::out.shape[1]+1] = fillvals
return out
Пример выполнения -
In [52]: X = np.array([(2.2, 2), (3, 3), (5, 1)])
In [53]: blockwise_jordan(X)
Out[53]:
array([[2.2, 1. , 0. , 0. , 0. , 0. ],
[0. , 2.2, 0. , 0. , 0. , 0. ],
[0. , 0. , 3. , 1. , 0. , 0. ],
[0. , 0. , 0. , 3. , 1. , 0. ],
[0. , 0. , 0. , 0. , 3. , 0. ],
[0. , 0. , 0. , 0. , 0. , 5. ]])
Оптимизация # 1
Мы можем заменить три последних шага для выполнения условное присвоение единиц и нулей, вот так -
out.flat[1::n+1] = 1
c = r[:-1].cumsum()-1
out[c,c+1] = 0