vectores una tutorial multiplicar matriz matrices imprimir guardar español datos crear con como python performance arrays numpy scipy

python - tutorial - Manera pitónica de crear una matriz numpy a partir de una lista de matrices numpy



numpy tutorial español pdf (5)

Agregaré mi propia versión de la respuesta de ~ unutbu. Similar a numpy_all_the way, pero cambia el tamaño dinámicamente si tiene un error de índice. Pensé que habría sido un poco más rápido para pequeños conjuntos de datos, pero es un poco más lento, la comprobación de límites reduce la velocidad de las cosas demasiado.

initial_guess = 1000 def my_numpy_all_the_way(k): arr=np.empty((initial_guess,M)) for x,row in enumerate(make_test_data(k)): try: arr[x]=row except IndexError: arr.resize((arr.shape[0]*2, arr.shape[1])) arr[x]=row arr.resize((k,M)) return arr

Genero una lista de matrices numpy unidimensionales en un bucle y más tarde convierto esta lista a una matriz nud 2d. Hubiera preasignado un 2d numpy array si sabía la cantidad de elementos antes de tiempo, pero no lo hago, por lo tanto, puse todo en una lista.

La maqueta está a continuación:

>>> list_of_arrays = map(lambda x: x*ones(2), range(5)) >>> list_of_arrays [array([ 0., 0.]), array([ 1., 1.]), array([ 2., 2.]), array([ 3., 3.]), array([ 4., 4.])] >>> arr = array(list_of_arrays) >>> arr array([[ 0., 0.], [ 1., 1.], [ 2., 2.], [ 3., 3.], [ 4., 4.]])

Mi pregunta es la siguiente:

¿Hay una mejor manera (en el rendimiento) para realizar la tarea de recopilar datos numéricos secuenciales (en mi caso matrices numpy) que ponerlos en una lista y luego crear un numpy.array (estoy creando un nuevo obj y copiando los datos)? ¿Hay una estructura de datos de matriz "ampliable" disponible en un módulo bien probado?

Un tamaño típico de mi matriz 2d sería entre 100x10 y 5000x10 flotadores

EDITAR: en este ejemplo estoy usando el mapa, pero en mi aplicación real tengo un bucle for


Incluso más simple que la respuesta de @Gill Bates, aquí hay un código de una línea:

np.stack(list_of_arrays, axis=0)


Lo que estás haciendo es la forma estándar. Una propiedad de matrices numpy es que necesitan memoria contigua. La única posibilidad de "agujeros" que puedo pensar es posible con el miembro de strides de PyArrayObject , pero eso no afecta la discusión aquí. Como las matrices numpy tienen memoria contigua y están "preasignadas", agregar una nueva fila / columna significa asignar nueva memoria, copiar datos y luego liberar la memoria anterior. Si haces eso mucho, no es muy eficiente.

Un caso en el que alguien podría no querer crear una lista y luego convertirla en una matriz numpy al final es cuando la lista contiene una gran cantidad de números: una numpy matriz de números ocupa mucho menos espacio que una lista de números nativa de Python (desde la lista nativa de Python almacena objetos de Python). Para los tamaños de matriz típicos, no creo que sea un problema.

Cuando crea su matriz final a partir de una lista de matrices, está copiando todos los datos en una nueva ubicación para la nueva matriz (2-d en su ejemplo). Esto es mucho más eficiente que tener una matriz numpy y hacer next = numpy.vstack((next, new_row)) cada vez que obtenga datos nuevos. vstack() copiará todos los datos para cada "fila".

Hubo un hilo en la lista de correo de discusión numpy hace algún tiempo que discutió la posibilidad de agregar un nuevo tipo de matriz numpy que permite extender / agregar eficientemente. Parece que hubo un gran interés en esto en ese momento, aunque no sé si algo salió de él. Es posible que desee mirar ese hilo.

Diría que lo que estás haciendo es muy pitónico y eficiente, así que a menos que realmente necesites algo más (¿más eficiencia espacial, tal vez?), Deberías estar bien. Así es como creo mis matrices numpy cuando no sé la cantidad de elementos en la matriz al principio.


Manera conveniente, usando numpy.concatenate . Creo que también es más rápido que la respuesta de @ unutbu:

In [32]: import numpy as np In [33]: list_of_arrays = list(map(lambda x: x * np.ones(2), range(5))) In [34]: list_of_arrays Out[34]: [array([ 0., 0.]), array([ 1., 1.]), array([ 2., 2.]), array([ 3., 3.]), array([ 4., 4.])] In [37]: shape = list(list_of_arrays[0].shape) In [38]: shape Out[38]: [2] In [39]: shape[:0] = [len(list_of_arrays)] In [40]: shape Out[40]: [5, 2] In [41]: arr = np.concatenate(list_of_arrays).reshape(shape) In [42]: arr Out[42]: array([[ 0., 0.], [ 1., 1.], [ 2., 2.], [ 3., 3.], [ 4., 4.]])


Supongamos que sabe que la matriz final arr nunca será mayor que 5000x10. Luego, puede asignar previamente una matriz de tamaño máximo, rellenarla con datos a medida que arr.resize por el ciclo, y luego usar arr.resize para arr.resize al tamaño descubierto después de salir del ciclo.

Las pruebas a continuación sugieren que hacerlo será un poco más rápido que construir listas intermedias de Python sin importar cuál sea el tamaño final de la matriz.

Además, arr.resize la memoria no utilizada, por lo que la huella de memoria final (aunque tal vez no intermedia) es menor que la utilizada por python_lists_to_array .

Esto muestra que numpy_all_the_way es más rápido:

% python -mtimeit -s"import test" "test.numpy_all_the_way(100)" 100 loops, best of 3: 1.78 msec per loop % python -mtimeit -s"import test" "test.numpy_all_the_way(1000)" 100 loops, best of 3: 18.1 msec per loop % python -mtimeit -s"import test" "test.numpy_all_the_way(5000)" 10 loops, best of 3: 90.4 msec per loop % python -mtimeit -s"import test" "test.python_lists_to_array(100)" 1000 loops, best of 3: 1.97 msec per loop % python -mtimeit -s"import test" "test.python_lists_to_array(1000)" 10 loops, best of 3: 20.3 msec per loop % python -mtimeit -s"import test" "test.python_lists_to_array(5000)" 10 loops, best of 3: 101 msec per loop

Esto muestra numpy_all_the_way usa menos memoria:

% test.py Initial memory usage: 19788 After python_lists_to_array: 20976 After numpy_all_the_way: 20348

test.py:

#!/usr/bin/env python import numpy as np import os def memory_usage(): pid=os.getpid() return next(line for line in open(''/proc/%s/status''%pid).read().splitlines() if line.startswith(''VmSize'')).split()[-2] N,M=5000,10 def python_lists_to_array(k): list_of_arrays = map(lambda x: x*np.ones(M), range(k)) arr = np.array(list_of_arrays) return arr def numpy_all_the_way(k): arr=np.empty((N,M)) for x in range(k): arr[x]=x*np.ones(M) arr.resize((k,M)) return arr if __name__==''__main__'': print(''Initial memory usage: %s''%memory_usage()) arr=python_lists_to_array(5000) print(''After python_lists_to_array: %s''%memory_usage()) arr=numpy_all_the_way(5000) print(''After numpy_all_the_way: %s''%memory_usage())