Me gustaría hacer lo siguiente:

for i in dimension1:
  for j in dimension2:
    for k in dimension3:
      for l in dimension4:
        B[k,l,i,j] = A[i,j,k,l]

sin el uso de bucles. Al final ambos a y B contienen la misma información pero indexado
de forma diferente.

Debo señalar que la dimensión de 1,2,3 y 4 pueden ser los mismos o diferentes. Así que un numpy.reformar() parece difícil.

  • ¿Cuáles son los dimension variables? ¿Te perdiste algún range llamadas?
InformationsquelleAutor sponce | 2014-05-29

5 Comentarios

  1. 22

    Por favor nota: Jaime de la respuesta es mejor. NumPy proporciona np.transpose precisamente para este propósito.


    O uso np.einsum; este es, quizás, una perversión de su uso previsto, pero la sintaxis es bastante agradable:

    In [195]: A = np.random.random((2,4,3,5))
    
    In [196]: B = np.einsum('klij->ijkl', A)
    
    In [197]: A.shape
    Out[197]: (2, 4, 3, 5)
    
    In [198]: B.shape
    Out[198]: (3, 5, 2, 4)
    
    In [199]: import itertools as IT    
    In [200]: all(B[k,l,i,j] == A[i,j,k,l] for i,j,k,l in IT.product(*map(range, A.shape)))
    Out[200]: True
    • Que es maravillosamente.. degenerados. <**rimshot**>
    • Creo que puedes hacer el «mal juego de palabras del día» premio!
    • Esta es la mejor solución para mí, como yo he hecho 7 dimensiones y múltiples swap o rollo es difícil. Yo en realidad aunque se acerca einsum pero de alguna manera se utiliza con la sintaxis incorrecta y no podía hacerlo. Muchas gracias!!!! Me encanta einsum mucho <3
  2. 59

    Canónica de la manera de hacer esto en numpy sería el uso de np.transponer‘s opcional permutación argumento. En su caso, para ir de ijkl a klij, la permutación es (2, 3, 0, 1), por ejemplo:

    In [16]: a = np.empty((2, 3, 4, 5))
    
    In [17]: b = np.transpose(a, (2, 3, 0, 1))
    
    In [18]: b.shape
    Out[18]: (4, 5, 2, 3)
  3. 11

    Podría rollaxis dos veces:

    >>> A = np.random.random((2,4,3,5))
    >>> B = np.rollaxis(np.rollaxis(A, 2), 3, 1)
    >>> A.shape
    (2, 4, 3, 5)
    >>> B.shape
    (3, 5, 2, 4)
    >>> from itertools import product
    >>> all(B[k,l,i,j] == A[i,j,k,l] for i,j,k,l in product(*map(range, A.shape)))
    True

    o tal vez swapaxes dos veces es más fácil seguir:

    >>> A = np.random.random((2,4,3,5))
    >>> C = A.swapaxes(0, 2).swapaxes(1,3)
    >>> C.shape
    (3, 5, 2, 4)
    >>> all(C[k,l,i,j] == A[i,j,k,l] for i,j,k,l in product(*map(range, A.shape)))
    True
    • +1 En una nota de lado, product(*map(range, A.shape)) puede ser escrito un poco más limpiamente como np.ndindex(*A.shape).
  4. 2

    Me gustaría ver en numpy.ndarray.forma y itertools.producto:

    import numpy, itertools
    A = numpy.ones((10,10,10,10))
    B = numpy.zeros((10,10,10,10))
    
    for i, j, k, l in itertools.product(*map(xrange, A.shape)):
        B[k,l,i,j] = A[i,j,k,l]

    Por «sin el uso de bucles» estoy asumiendo que significa «sin el uso de bucles anidados», por supuesto. A menos que haya alguna numpy construido-en el que hace esto, creo que este es su mejor apuesta.

    • En NumPy, uno de los objetivos generales de evitar bucles es para obtener el C parte del código para hacer el trabajo pesado. Que significa bucles anidados o itertools.product son tanto indeseable.
    • Gracias metaperture ! ¿Qué estás sugiriendo user2357112 ? Que rutina de C puede hacer eso?
  5. 1

    También se puede aprovechar numpy.moveaxis() para movimiento la necesaria ejes a las ubicaciones deseadas. Aquí está una ilustración, robando el ejemplo de Jaime de la respuesta:

    In [160]: a = np.empty((2, 3, 4, 5))
    
    # move the axes that are originally at positions [0, 1] to [2, 3]
    In [161]: np.moveaxis(a, [0, 1], [2, 3]).shape 
    Out[161]: (4, 5, 2, 3)

Dejar respuesta

Please enter your comment!
Please enter your name here