3
votes

aplatissement d'un tableau numpy le long des colonnes, dans l'ordre: triangle inférieur, diagonal, triangle supérieur

Voici un problème que j'essaie de résoudre. Disons que nous avons un tableau carré:

In [16]: arr[np.tril(arr, k=-1) != 0]
Out[16]: array([ 5,  9, 10, 13, 14, 15])   # not correct!

In [17]: np.diag(arr)
Out[17]: array([ 1,  6, 11, 16])

In [18]: arr[np.triu(arr, k=1) != 0]
Out[18]: array([ 2,  3,  4,  7,  8, 12])  # not correct!

Ce que j'aimerais avoir, c'est d'aplatir ce tableau dans un ordre spécifique: d'abord, je veux aplatir le triangle inférieur le long de l'axe-0 et puis choisissez la diagonale, et enfin aplatissez à nouveau le triangle supérieur le long de l'axe 0, ce qui donnerait finalement le tableau aplati comme suit:

#              | lower triangle     |diag.elements| upper triangle  |  
res = np.array([5, 9, 13, 10, 14, 15, 1, 6, 11, 16, 2, 3, 7, 4, 8, 12])

Voici ma solution partielle jusqu'à présent, qui ne donne pas encore le résultat souhaité.

In [10]: arr
Out[10]: 
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

Enfin, pour concaténer ces 3 résultats intermédiaires. Comment indexer correctement pour obtenir le résultat souhaité? Sinon, existe-t-il d'autres moyens de résoudre ce problème?


2 commentaires

Regardez np.tri pour voir comment cet ensemble de fonctions génère les indices. Vous pourrez peut-être rationaliser les choses, surtout si vous le faites à plusieurs reprises sur différents tableaux arr .


@hpaulj voudriez-vous élaborer plus à ce sujet en guise de réponse, s'il vous plaît? J'adorerais voir un autre moyen de résoudre ce problème.


3 Réponses :


2
votes

Utilisez la transpose:

[ 5  9 13 10 14 15  1  6 11 16  2  3  7  4  8 12]

Output:

lower = np.tril(a, -1).T.ravel()
diag = np.diag(a)
upper = np.triu(a, 1).T.ravel()

result = np.concatenate([lower[lower != 0], diag, upper[upper != 0]])

print(result)


0 commentaires

2
votes

J'utilise l'index pour sélectionner ( numpy diffusion)

ary=ary.T

i,c=ary.shape
x=np.arange(i)
y=np.arange(c)
np.concatenate([ary[x[:,None]<y],ary[x[:,None]==y],ary[x[:,None]>y]])
Out[1065]: array([ 5,  9, 13, 10, 14, 15,  1,  6, 11, 16,  2,  3,  7,  4,  8, 12])


1 commentaires

@ kmario23 vérifiez la mise à jour, il suffit d'ajouter le T :-)



3
votes

En voici un basé sur le masquage et concaténation / empilement -

n = len(arr)
r = np.arange(n)
mask = r[:,None]<r
diag_mask = r[:,None]==r
comp_mask = np.vstack((mask[None],diag_mask[None],mask.T[None]))
out = np.broadcast_to(arr.T,(3,n,n))[comp_mask]

Un autre basé uniquement sur le masquage -

In [50]: r = np.arange(len(arr))

In [51]: mask = r[:,None]<r

In [54]: np.concatenate((arr.T[mask],np.diag(arr),arr.T[mask.T]))
Out[54]: array([ 5,  9, 13, 10, 14, 15,  1,  6, 11, 16,  2,  3,  7,  4,  8, 12])


0 commentaires