A menudo, estoy construyendo una matriz por iteración a través de algunos datos, por ejemplo:

my_array = []
for n in range(1000):
  # do operation, get value 
  my_array.append(value)
# cast to array
my_array = array(my_array)

Me encuentro con que tengo que generar primero una lista y, a continuación, cast (con la «matriz») a una matriz. Hay una forma de evitar estos? Todos estos castings de desorden en el código… ¿cómo puedo construir de forma iterativa hasta «mi_matriz», que es una matriz desde el inicio?

  • ¿qué sucede si usted no lo hace?
  • La razón numpy es tan rápido, en primer lugar, es que opera con constante de las matrices de tamaño y no listas dinámicas. Para deshacerse de él sólo para reducir el «desorden» en el código no es la mejor manera de ir. Si usted sabe el tamaño de antemano (1000) asignar previamente de ello. Si no – la construcción de la lista es sin duda la mejor manera de ir, como las listas de python [] son bastante eficientes.
InformationsquelleAutor | 2010-04-14

3 Comentarios

  1. -2

    Si entiendo tu pregunta correctamente, esto debe hacer lo que usted desea:

    # the array passed into your function
    ax = NP.random.randint(10, 99, 20).reshape(5, 4)
    
    # just define a function to operate on some data
    fnx = lambda x : NP.sum(x)**2
    
    # apply the function directly to the numpy array
    new_row = NP.apply_along_axis(func1d=fnx, axis=0, arr=ax)
    
    # 'append' the new values to the original array
    new_row = new_row.reshape(1,4)
    ax = NP.vstack((ax, new_row))
    • Como este es el aceptado la respuesta que tengo que decir esto: he visto vstack utiliza mucho como esta. Uno debe ser consciente de que esto es realmente(!) no performante. Si usted construye una gran variedad de esta manera, usted hace un montón de memoria innecesaria la operación de copia. ver las respuestas abajo
  2. 32

    NumPy ofrece una fromiter’ método:

    def myfunc(n):
        for i in range(n):
            yield i**2
    
    
    np.fromiter(myfunc(5), dtype=int)

    que los rendimientos

    array([ 0,  1,  4,  9, 16])
    • Cuando se utiliza np.fromiter y usted sabe el tamaño de la matriz de antemano, usted puede pasar como parámetro para la matriz obtiene pre-asignados. Esto aumenta el rendimiento enormemente. Así, en el ejemplo anterior, hacer: np.fromiter(myfunc(5), dtype=int, count=5)
  3. 15

    La forma recomendada de hacerlo es asignar previamente antes de que el bucle y el uso de segmentación de datos y de indexación para insertar

    my_array = numpy.zeros(1,1000)
    for i in xrange(1000):
        #for 1D array
        my_array[i] = functionToGetValue(i)
        #OR to fill an entire row
        my_array[i:] = functionToGetValue(i)
        #or to fill an entire column
        my_array[:,i] = functionToGetValue(i)

    numpy hace proporcionar un array.resize() método, pero esto va a ser mucho más lento debido a que el costo de la reasignación de memoria dentro de un bucle. Si usted debe tener flexibilidad, entonces me temo que la única manera es crear un array de un list.

    EDIT: Si usted está preocupado de que pueda asignar demasiada memoria para los datos, yo uso el método anterior a la sobre-asignar y, a continuación, cuando el bucle se realiza, lop de los bits no utilizados de la matriz de uso de la array.resize(). Este será mucho, mucho más rápido que constantemente la reasignación de la matriz dentro del bucle.

    EDIT: En respuesta a @user248237 comentario, suponiendo que sabes que en cualquier una de las dimensiones de la matriz (por simplificar):

    my_array = numpy.array(10000, SOMECONSTANT)
    
    for i in xrange(someVariable):
        if i >= my_array.shape[0]:
            my_array.resize((my_array.shape[0]*2, SOMECONSTANT))
    
        my_array[i:] = someFunction()
    
    #lop off extra bits with resize() here

    El principio general es la de «asignar más de lo que usted piensa que usted necesita, y si las cosas cambian, cambiar el tamaño de la matriz cuantas veces como sea posible». Duplicar el tamaño podría ser considerado como excesivo, pero en realidad este es el método utilizado por varias estructuras de datos en varias bibliotecas estándar en otros idiomas (java.util.Vector hace esto por defecto, por ejemplo. Creo que varias de las implementaciones de std::vector en C++ hacerlo así).

    • ¿Qué pasa si no sé el tamaño antes de tiempo?
    • Eso tiene sentido, pero supongo que construyeron matrices de esta manera, mediante la asignación de más de lo que necesita — ¿cómo puedo iterar sobre la matriz? Si me asignar numpy.zeros(1, 1000), pero sólo el uso de 50 elementos, no quiero repetir hasta que llegué a un cero… el enfoque de overallocating parece crear esta extraña situación en la que cada tipo de datos array requerirá un diferente «stop» condición de bucle. Hay una forma de evitar esto?
    • Como ya he dicho, usted puede hacer una llamada final a resize() cuando el bucle está hecho. Si reduce el tamaño de la matriz para el tamaño correcto, usted va a tirar todo el cero elementos.
    • Alguien debería escribir algo parecido a la stl::vector enfoque en el que se asigna bloques de como las cosas se anexa. . .
    • El Python matriz del módulo módulo puede hacer esto, para el debate, véase la respuesta a la esta pregunta.

Dejar respuesta

Please enter your comment!
Please enter your name here