sumar - transpuesta de una matriz en python numpy
¿Cómo acceder a la columna i de una matriz multidimensional NumPy? (7)
Aunque la pregunta ha sido respondida, permítanme mencionar algunos matices.
Digamos que está interesado en la primera columna de la matriz
arr = numpy.array([[1, 2],
[3, 4],
[5, 6]])
Como ya sabe por otras respuestas, para obtenerlo en forma de "vector de fila" (matriz de forma (3,)
), utilice el corte de corte:
arr_c1_ref = arr[:, 1] # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy() # creates a copy of the 1st column of the arr
Para verificar si una matriz es una vista o una copia de otra matriz, puede hacer lo siguiente:
arr_c1_ref.base is arr # True
arr_c1_copy.base is arr # False
ver ndarray.base .
Además de la diferencia obvia entre los dos (la modificación de arr_c1_ref
afectará a arr
), el número de pasos de bytes para atravesar cada uno de ellos es diferente:
arr_c1_ref.strides[0] # 8 bytes
arr_c1_copy.strides[0] # 4 bytes
ver strides ¿Porque es esto importante? Imagina que tienes una matriz muy grande A
lugar de la arr
:
A = np.random.randint(2, size=(10000,10000), dtype=''int32'')
A_c1_ref = A[:, 1]
A_c1_copy = A[:, 1].copy()
y desea calcular la suma de todos los elementos de la primera columna, es decir, A_c1_ref.sum()
o A_c1_copy.sum()
. Usar la versión copiada es mucho más rápido:
%timeit A_c1_ref.sum() # ~248 µs
%timeit A_c1_copy.sum() # ~12.8 µs
Esto se debe a la cantidad diferente de pasos mencionados anteriormente:
A_c1_ref.strides[0] # 40000 bytes
A_c1_copy.strides[0] # 4 bytes
Aunque podría parecer que usar copias de columnas es mejor, no siempre es así porque hacer una copia lleva tiempo y usa más memoria (en este caso me tomó aproximadamente 200 µs crear la A_c1_copy
). Sin embargo, si necesitamos la copia en primer lugar, o tenemos que hacer muchas operaciones diferentes en una columna específica de la matriz y estamos de acuerdo con sacrificar la memoria por la velocidad, entonces hacer una copia es el camino a seguir.
En el caso de que estemos interesados en trabajar principalmente con columnas, podría ser una buena idea crear nuestra matriz en orden de columna mayor (''F'') en lugar de orden de fila mayor (''C'') (que es el valor predeterminado ), y luego haga el corte como antes para obtener una columna sin copiarla:
A = np.asfortranarray(A) # or np.array(A, order=''F'')
A_c1_ref = A[:, 1]
A_c1_ref.strides[0] # 4 bytes
%timeit A_c1_ref.sum() # ~12.6 µs vs ~248 µs
Ahora, realizar la operación de suma (o cualquier otra) en una vista de columna es mucho más rápido.
Finalmente, permítanme señalar que la transposición de una matriz y el uso de la división de filas es lo mismo que usar la división de columnas en la matriz original, porque la transposición se realiza simplemente intercambiando la forma y los pasos de la matriz original.
A.T[1,:].strides[0] # 40000
Supongamos que tengo:
test = numpy.array([[1, 2], [3, 4], [5, 6]])
test[i]
me llega a la línea de la matriz (por ejemplo, [1, 2]
). ¿Cómo puedo acceder a la columna i ? (por ejemplo, [1, 3, 5]
). Además, ¿sería una operación costosa?
Para obtener varias columnas independientes, solo:
> test[:,[0,2]]
obtendrás colums 0 y 2
También puedes transponer y devolver una fila:
In [4]: test.T[0]
Out[4]: array([1, 3, 5])
Y si desea acceder a más de una columna a la vez, puede hacerlo:
>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
[3, 5],
[6, 8]])
>>> test
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> ncol = test.shape[1]
>>> ncol
5L
A continuación, puede seleccionar la columna 2ª - 4ª de esta manera:
>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
[6, 7, 8]])
>>> test[:,0]
array([1, 3, 5])
Similar,
>>> test[1,:]
array([3, 4])
te permite acceder a las filas. Esto se trata en la Sección 1.4 (Indexación) de la referencia NumPy . Esto es rápido, al menos en mi experiencia. Es ciertamente mucho más rápido que acceder a cada elemento en un bucle.
>>> test[:,0]
array([1, 3, 5])
este comando te da un vector de fila, si solo quieres recorrerlo, está bien, pero si quieres hstack con alguna otra matriz con dimensión 3xN, tendrás
ValueError: todas las matrices de entrada deben tener el mismo número de dimensiones
mientras
>>> test[:,[0]]
array([[1],
[3],
[5]])
le da un vector de columna, para que pueda hacer la operación de concatenar o hstack.
p.ej
>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
[3, 4, 3],
[5, 6, 5]])