python - promedio - Matrices crecientes en columnas en NumPy
producto de matrices python numpy (4)
El hstack puede trabajar en arrays de tamaño cero:
import numpy as np
N = 5
M = 15
a = np.ndarray(shape = (N, 0))
for i in range(M):
b = np.random.rand(N, 1)
a = np.hstack((a, b))
En Python puro puedes aumentar las matrices columna por columna con bastante facilidad:
data = []
for i in something:
newColumn = getColumnDataAsList(i)
data.append(newColumn)
La matriz de NumPy no tiene la función de añadir. La función hstack
no funciona en arreglos de tamaño cero, por lo tanto, lo siguiente no funcionará:
data = numpy.array([])
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
data = numpy.hstack((data, newColumn)) # ValueError: arrays must have same number of dimensions
Por lo tanto, mis opciones son eliminar la inicialización dentro del bucle con la condición apropiada:
data = None
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
if data is None:
data = newColumn
else:
data = numpy.hstack((data, newColumn)) # works
... o para usar una lista de Python y convertir es posterior a la matriz:
data = []
for i in something:
newColumn = getColumnDataAsNumpyArray(i)
data.append(newColumn)
data = numpy.array(data)
Ambas variantes parecen un poco torpes de ser. ¿Hay mejores soluciones?
En general, es costoso seguir reasignando la matriz NumPy, por lo que su tercera solución es realmente el mejor rendimiento.
Sin embargo, creo que hstack
hará lo que quieras: la clave está en el mensaje de error,
ValueError: las matrices deben tener el mismo número de dimensiones`
Supongo que newColumn tiene dos dimensiones (en lugar de un vector 1D), por lo que necesita que los datos también tengan dos dimensiones ..., por ejemplo, data = np.array([[]])
, o alternativamente haga que newColumn sea un Vector 1D (en general, si las cosas son 1D es mejor mantenerlas en NumPy, por lo que las transmisiones, etc. funcionan mejor). en cuyo caso, use np.squeeze(newColumn)
y hstack
o vstack
debería funcionar con su definición original de los datos.
NumPy en realidad tiene una función de adición , que parece que podría hacer lo que quieras, por ejemplo,
import numpy as NP
my_data = NP.random.random_integers(0, 9, 9).reshape(3, 3)
new_col = NP.array((5, 5, 5)).reshape(3, 1)
res = NP.append(my_data, new_col, axis=1)
su segundo fragmento (hstack) funcionará si agrega otra línea, por ejemplo,
my_data = NP.random.random_integers(0, 9, 16).reshape(4, 4)
# the line to add--does not depend on array dimensions
new_col = NP.zeros_like(my_data[:,-1]).reshape(-1, 1)
res = NP.hstack((my_data, new_col))
hstack
da el mismo resultado que concatenate((my_data, new_col), axis=1)
, no estoy seguro de cómo se comparan en cuanto al rendimiento.
Si bien esa es la respuesta más directa a su pregunta, debo mencionar que el bucle a través de una fuente de datos para poblar un objetivo a través de un anexo , aunque está bien en Python, no es un número idiomático. Este es el por qué:
la inicialización de una matriz NumPy es relativamente costosa , y con este patrón de Python convencional, incurres en ese costo, más o menos, en cada iteración de bucle (es decir, cada adición a una matriz NumPy es casi como inicializar una matriz nueva con un tamaño diferente).
Por esa razón, el patrón común en NumPy para la adición iterativa de columnas a una matriz 2D es inicializar una matriz de destino vacía una vez (o pre-asignar una única matriz NumPy 2D que tiene todas las columnas vacías) para llenar sucesivamente esas columnas vacías establecer el desplazamiento de columna deseado (índice): es mucho más fácil de mostrar que de explicar:
>>> # initialize your skeleton array using ''empty'' for lowest-memory footprint
>>> M = NP.empty(shape=(10, 5), dtype=float)
>>> # create a small function to mimic step-wise populating this empty 2D array:
>>> fnx = lambda v : NP.random.randint(0, 10, v)
rellene la matriz NumPy como en el OP, excepto que cada iteración simplemente restablece los valores de M en sucesivas compensaciones por columnas
>>> for index, itm in enumerate(range(5)):
M[:,index] = fnx(10)
>>> M
array([[ 1., 7., 0., 8., 7.],
[ 9., 0., 6., 9., 4.],
[ 2., 3., 6., 3., 4.],
[ 3., 4., 1., 0., 5.],
[ 2., 3., 5., 3., 0.],
[ 4., 6., 5., 6., 2.],
[ 0., 6., 1., 6., 8.],
[ 3., 8., 0., 8., 0.],
[ 5., 2., 5., 0., 1.],
[ 0., 6., 5., 9., 1.]])
por supuesto, si no sabe de antemano qué tamaño debería tener su matriz, cree una mucho más grande de lo que necesita y recorte las partes "no utilizadas" cuando termine de rellenarlas
>>> M[:3,:3]
array([[ 9., 3., 1.],
[ 9., 6., 8.],
[ 9., 7., 5.]])
Por lo general, no sigue cambiando el tamaño de una matriz NumPy cuando la crea. ¿Qué no te gusta de tu tercera solución? Si es una matriz / matriz muy grande, entonces vale la pena asignar la matriz antes de comenzar a asignar sus valores:
x = len(something)
y = getColumnDataAsNumpyArray.someLengthProperty
data = numpy.zeros( (x,y) )
for i in something:
data[i] = getColumnDataAsNumpyArray(i)