Учитывая этот массив NumPy

[[200.       202.08165 ]
 [189.60295  190.32434 ]
 [189.19751  188.7867  ]
 [162.15639  164.05934 ]]

Я хочу получить этот массив

[[200.       190.32434 ]
 [189.60295  188.7867  ]
 [189.19751  164.05934 ]]

То же самое для 3 столбцов, учитывая этот массив

[[200.       202.08165    187.8392 ]
 [189.60295  190.32434    167.93082]
 [189.19751  188.7867     199.2839 ]
 [162.15639  164.05934    200.92   ]]

Я хочу получить этот массив

[[200.       190.32434    199.2839 ]
 [189.60295  188.7867     200.92   ]]

Любой векторизованный способ достижения этого для любого количества столбцов и строк? np.diag и np.diagonal, кажется, дают мне одну диагональ, но мне нужно, чтобы все они были сложены.

1
Nico 2 Май 2020 в 12:39

2 ответа

Ну, это похоже на специализированный случай хранения диагональных элементов. Вот одно векторизованное решение, использующее masking -

def keep_diag(a):    
    m,n = a.shape
    i,j = np.ogrid[:m,:n]
    mask = (i>=j) & ((i-m+n)<=j)
    return a.T[mask.T].reshape(n,-1).T

Большая часть хитрости находится на этапе создания mask, который при маскировке входным массивом извлекает из него необходимые элементы.

Образцы прогонов -

In [105]: a
Out[105]: 
array([[ 0, 16],
       [11, 98],
       [81, 63],
       [83, 20]])

In [106]: keep_diag(a)
Out[106]: 
array([[ 0, 98],
       [11, 63],
       [81, 20]])

In [102]: a
Out[102]: 
array([[10,  2, 66],
       [44, 18, 35],
       [70,  8, 31],
       [12, 27, 86]])

In [103]: keep_diag(a)
Out[103]: 
array([[10, 18, 31],
       [44,  8, 86]])
0
Divakar 2 Май 2020 в 10:07

Вы все еще можете использовать np.diagonal():

import numpy as np
b= np.array([[200.     , 202.08165, 187.8392 ],
             [189.60295, 190.32434, 167.93082],
             [189.19751, 188.7867 , 199.2839 ],
             [162.15639, 164.05934, 200.92   ]])  

diags = np.asarray([b[i:,:].diagonal() for i in range(b.shape[0]-b.shape[1]+1)])
0
Asen Christov 2 Май 2020 в 09:59