Inicializar múltiples matrices numpy (asignación múltiple) – como MATLAB deal ()

No pude encontrar nada que describiera cómo hacer esto, lo que lleva a creer que no lo estoy haciendo de la manera idónea de Python idiomática. También se agradecería el asesoramiento sobre la forma “adecuada” de Python para hacer esto.

Tengo un grupo de variables para un registrador de datos que estoy escribiendo (longitud de registro arbitraria, con una longitud máxima conocida). En MATLAB, los inicializaría a todos como matrices 1-D de ceros de longitud n, n más grande que el número de entradas que jamás vería, asignaría cada variable(measurement_no) = data_point elemento individual variable(measurement_no) = data_point en el ciclo de registro y recortaría la Ceros extraños al terminar la medición. La inicialización se vería así:

 [dData gData cTotalEnergy cResFinal etc] = deal(zeros(n,1)); 

¿Hay alguna manera de hacer esto en Python / NumPy, por lo que tampoco tengo que poner cada variable en su propia línea?

 dData = np.zeros(n) gData = np.zeros(n) etc. 

También preferiría no solo hacer una gran matriz, porque hacer un seguimiento de qué columna es qué variable es desagradable. ¿Quizás la solución es hacer la matriz (length x numvars) y asignar los cortes de columna a las variables individuales?

EDITAR: Supongamos que voy a tener muchos vectores de la misma longitud para cuando esto termine; por ejemplo, mi procesamiento posterior toma cada archivo de registro, calcula un grupo de métricas separadas (> 50), las almacena y repite hasta que se procesan todos los registros. Luego genero histogtwigs, medias / maxes / sigmas / etc. Para todas las diversas métricas que he calculado. Ya que la inicialización de más de 50 vectores no es fácil en Python, ¿cuál es la mejor manera de hacer esto (código más limpio y rendimiento decente)?

Si está realmente motivado para hacer esto en una sola línea, podría crear una (n_vars, ...) matriz de ceros, luego descomprimirlo a lo largo de la primera dimensión:

 a, b, c = np.zeros((3, 5)) print(a is b) # False 

Otra opción es usar una comprensión de lista o una expresión generadora:

 a, b, c = [np.zeros(5) for _ in range(3)] # list comprehension d, e, f = (np.zeros(5) for _ in range(3)) # generator expression print(a is b, d is e) # False False 

¡Pero ten cuidado! Podría pensar que usar el operador * en una lista o tupla que contiene su llamada a np.zeros() lograría lo mismo, pero no:

 h, i, j = (np.zeros(5),) * 3 print(h is i) # True 

Esto se debe a que la expresión dentro de la tupla se evalúa primero. np.zeros(5) por lo tanto, solo se llama una vez, y cada elemento en la tupla repetida termina siendo una referencia a la misma matriz. Esta es la misma razón por la que no puedes usar a = b = c = np.zeros(5) .

A menos que realmente necesite asignar un gran número de variables de matriz vacía y realmente se preocupe por hacer que su código sea compacto (!), Recomendaría inicializarlas en líneas separadas para facilitar la lectura.

Nada malo o no pythonico con

 dData = np.zeros(n) gData = np.zeros(n) etc. 

Podría ponerlos en una línea, pero no hay ninguna razón particular para hacerlo.

 dData, gData = np.zeros(n), np.zeros(n) 

No intente dData = gData = np.zeros(n) , porque un cambio a dData cambia gData (apuntan al mismo objeto). Por el mismo motivo, normalmente no desea utilizar x = y = [] .

El deal en MATLAB es una conveniencia, pero no es mágico. Así es como Octave lo implementa.

 function [varargout] = deal (varargin) if (nargin == 0) print_usage (); elseif (nargin == 1 || nargin == nargout) varargout(1:nargout) = varargin; else error ("deal: nargin > 1 and nargin != nargout"); endif endfunction 

En contraste con Python, en Octave (y probablemente MATLAB)

 one=two=three=zeros(1,3) 

Asigna diferentes objetos a las 3 variables.

Observe también cómo MATLAB habla sobre el deal como una forma de asignar contenidos de celdas y estructuras de arreglos. http://www.mathworks.com/company/newsletters/articles/whats-the-big-deal.html

Si coloca sus datos en una collections.defaultdict , no tendrá que hacer ninguna inicialización explícita. Todo se inicializará la primera vez que se use.

 import numpy as np import collections n = 100 data = collections.defaultdict(lambda: np.zeros(n)) for i in range(1, n): data['g'][i] = data['d'][i - 1] # ... 

¿Qué hay de usar el map :

 import numpy as np n = 10 # Number of data points per array m = 3 # Number of arrays being initialised gData, pData, qData = map(np.zeros, [n] * m)