3
votes

Remodeler le tableau NumPy 2D en 3D avec des lignes récurrentes

J'ai un tableau NumPy comme suit:

[[[ 6.  7.  8.  9. 10.]
  [ 1.  2.  3.  4.  5.]]    
 [[ 0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.]]  
 [[ 0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.]]]

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

[[[ 6.  7.  8.  9. 10.]
  [ 1.  2.  3.  4.  5.]]    
 [[11. 12. 13. 14. 15.]
  [ 6.  7.  8.  9. 10.]]    
 [[16. 17. 18. 19. 20.]
  [11. 12. 13. 14. 15.]]]

Je cherche à organiser de telle sorte qu'il ressemble à ceci:

x=np.zeros([3,2,5])
for i in range(len(arr)):
    x[i]=arr[i:i+2,:][::-1]

Donc essentiellement un tableau 3D avec 2x5 dans chaque ligne du tableau. Le code que j'ai essayé est:

[[[6,7,8,9,10],
  [1,2,3,4,5]],
 [[11,12,13,14,15],
  [6,7,8,9,10]],
 [[16,17,18,19,20],
  [11,12,13,14,15]]]

Mais cela donne le résultat ci-dessous:

arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])


1 commentaires

Lorsque j'essaie d'exécuter votre tentative de code, j'obtiens une erreur, comme je m'y attendais. Si je change la range de la boucle en range (x.shape [0]) (c'est-à-dire range (len (x)) ), j'obtiens le résultat que vous voulez. Êtes-vous sûr que le tableau que vous avez collé provient de l'entrée et du code ci-dessus?


3 Réponses :


0
votes

Pas besoin d'utiliser de boucles. Le découpage suffit:

x = np.zeros([3,2,5], dtype=int)
x[:,0] = arr[-3:,:]
x[:,1] = arr[:3,:]

Essentiellement, vous attribuez la 0-ème ligne de toutes les pages aux 3 dernières lignes de arr et la 1ère ligne de toutes les pages à la première 3 lignes de arr.


0 commentaires

1
votes

Vous pouvez utiliser quelques astuces de foulée pour construire votre tableau sous forme de fenêtre coulissante multidimensionnelle sur votre tableau d'entrée:

>>> out_strides = in_strides[:1] + in_strides 
... out_shape = (3, 3, 5)  # 3 + 3 == 6 > arr.shape[0] + 1 == 5
... np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
array([[[         1,              2,              3,              4,
                  5],
    [             6,              7,              8,              9,
                 10],
    [            11,             12,             13,             14,
                 15]],

   [[             6,              7,              8,              9,
                 10],
    [            11,             12,             13,             14,
                 15],
    [            16,             17,             18,             19,
                 20]],

   [[            11,             12,             13,             14,
                 15],
    [            16,             17,             18,             19,
                 20],
    [           384,            193, 94379169559968,              0,
                  0]]])

Ce qui précède fonctionnera en toute sécurité tant que out_shape [-1] et sum (out_shape [: 2]) . Ce sont des contraintes qui rendent la fenêtre glissante significative à l'intérieur du tableau d'origine, et votre cas d'utilisation réel doit naturellement les respecter.

Remarques importantes:

  • Si les inégalités ci-dessus ne tiennent pas, la fenêtre glissante glissera volontiers hors de la plage de mémoire de votre tableau, et vous commencerez silencieusement à voir des éléments de matrice de déchets:

    import numpy as np 
    arr = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]]) 
    
    # compute the strides and shape of the output array
    in_strides = arr.strides 
    out_strides = in_strides[:1] + in_strides 
    out_shape = (3, 2) + arr.shape[-1:]  # keep the last dimension's size
    strided = np.lib.stride_tricks.as_strided(arr, strides=out_strides, shape=out_shape)
    out_arr = strided[:, ::-1, :].copy()  # use a copy to stay safe
    
  • Si vous ne modifiez pas votre tableau par la suite, et alors seulement, vous pouvez omettre l'appel final .copy () dans ce qui précède. Cela vous donnera un tableau strided qui partage la mémoire avec le tableau d'origine, mais ce qui est plus important, les lignes du tableau partageront la mémoire les unes avec les autres. Ce n'est pas ce que vous voulez habituellement, mais si votre tableau réel est très grand et vous savez que vous pouvez supposer en toute sécurité que les valeurs ne seront pas mutées indépendamment, l'empreinte mémoire peut avoir de l'importance. Un autre aspect à considérer est que l'appel de .copy () sur le résultat vous donnera un bloc de mémoire contigu, ce qui est probablement meilleur pour les performances sur toute la ligne, en fonction de ce que vous prévoyez de faire. le tableau résultant.


0 commentaires

1
votes

Nous pouvons tirer parti de np.lib.stride_tricks. as_strided basé sur scikit-image's view_as_windows pour obtenir des fenêtres coulissantes. Plus d'informations sur l'utilisation de as_strided basé sur view_as_windows .

In [15]: from skimage.util.shape import view_as_windows

In [16]: view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]
Out[16]: 
array([[[ 6,  7,  8,  9, 10],
        [ 1,  2,  3,  4,  5]],

       [[11, 12, 13, 14, 15],
        [ 6,  7,  8,  9, 10]],

       [[16, 17, 18, 19, 20],
        [11, 12, 13, 14, 15]]])

Ce serait simplement une vue dans le tableau d'entrée. Par conséquent, il n'y a aucune surcharge de mémoire supplémentaire et une durée d'exécution pratiquement gratuite. Si vous voulez une sortie avec son propre espace mémoire, ajoutez-y .copy () , c'est-à-dire x.copy().

Exemple d'exécution -

from skimage.util.shape import view_as_windows

x = view_as_windows(arr,(2,arr.shape[1]))[:,0,::-1]


0 commentaires