Atributos de arreglos NumPy
En este capítulo conoceremos algunas propiedades básicas de los arreglos de NumPy.
El número de dimensiones de un arreglo NumPy se denomina rango (rank); el rango es la cantidad de ejes, es decir, las dimensiones del arreglo.
Un arreglo unidimensional tiene rango 1, un arreglo bidimensional tiene rango 2, y así sucesivamente.
En NumPy, cada dimensión de un arreglo se denomina eje (axis), es decir, una dimensión (dimensions).
Por ejemplo, un arreglo bidimensional puede verse como un "arreglo unidimensional de arreglos unidimensionales": cada elemento del arreglo exterior es a su vez un arreglo unidimensional.
El eje 0 corresponde a la dirección del arreglo más externo, el eje 1 es la dirección del arreglo interno, y así sucesivamente.
El número de ejes —el rango— es la dimensionalidad del arreglo.
Muchas funciones de NumPy admiten el parámetro axis.
Para un arreglo bidimensional, axis=0 significa operar a lo largo del eje 0, es decir, operar sobre cada columna; axis=1 significa operar a lo largo del eje 1, es decir, operar sobre cada fila.
A continuación, tomando como ejemplo un arreglo bidimensional con shape (2, 3), se muestran intuitivamente las direcciones de los dos ejes y el significado de cada atributo:
axis indica "en qué dirección comprimir", no "qué fila/columna": sumar a lo largo de axis=0 comprime varias filas en una sola, por lo que el resultado es la suma de cada columna.
Ejemplo
a = np.array([[1, 2, 3], [4, 5, 6]])
# Sumar a lo largo del eje 0: comprimir en la dirección de las filas, sumar cada columna
print(a.sum(axis=0))
# Sumar a lo largo del eje 1: comprimir en la dirección de las columnas, sumar cada fila
print(a.sum(axis=1))
El resultado es:
[5 7 9] [ 6 15]
La siguiente demostración interactiva permite apreciar más intuitivamente la dirección de suma de los dos ejes; haz clic en el botón para alternar:
a.sum(axis=0) → [5 7 9], comprime los elementos de cada columna en un solo número a lo largo del eje 0Las propiedades más importantes del objeto ndarray en NumPy son:
| Atributo | Descripción |
|---|---|
ndarray.ndim | Rango (rank) del arreglo, es decir, el número de dimensiones o ejes del arreglo. |
ndarray.shape | Dimensiones del arreglo; representa el tamaño del arreglo en cada eje. Para un arreglo bidimensional (matriz), representa su número de filas y columnas. |
ndarray.size | El número total de elementos del arreglo, igual alndarray.shapeproducto de los tamaños de cada eje en shape. |
ndarray.dtype | El tipo de datos de los elementos del arreglo. |
ndarray.itemsize | El tamaño de cada elemento del arreglo, en bytes. |
ndarray.flags | Contiene información sobre la disposición en memoria, como si es contigua en C o Fortran, si es de solo lectura, etc. |
ndarray.real | La parte real de cada elemento del arreglo (si el tipo de elemento es complejo). |
ndarray.imag | La parte imaginaria de cada elemento del arreglo (si el tipo de elemento es complejo). |
ndarray.data | El búfer que realmente almacena los elementos del arreglo; normalmente se accede a los elementos mediante índices, no se usa directamente esta propiedad. |
ndarray.ndim
ndarray.ndim se utiliza para obtener el número de dimensiones del arreglo (es decir, el número de ejes), o sea, el rango.
Ejemplo
a = np.arange(24)
print(a.ndim) # a ahora tiene una sola dimensión
# Ajustar su tamaño con reshape para que pase a tener 2 páginas, 4 filas y 3 columnas
b = a.reshape(2, 4, 3) # b ahora tiene tres dimensiones
print(b.ndim)
El resultado es:
1 3
ndarray.shape
ndarray.shape representa las dimensiones del arreglo y devuelve una tupla; la longitud de esta tupla es el número de dimensiones, es decir, el atributo ndim (rango).
Por ejemplo, el shape de un arreglo bidimensional representa su "número de filas" y "número de columnas".
El orden de la tupla shape coincide con el orden de los ejes: el elemento 0 es el tamaño del eje 0 (número de filas), el elemento 1 es el tamaño del eje 1 (número de columnas).
Ejemplo
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
El resultado es:
(2, 3)
ndarray.shape también se puede utilizar para ajustar el tamaño del arreglo.
Ejemplo
a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
print(a)
El resultado es:
[[1 2] [3 4] [5 6]]
NumPy también proporciona la función reshape para ajustar el tamaño del arreglo.
Ejemplo
a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b)
El resultado es:
[[1 2] [3 4] [5 6]]
La diferencia entre ambos métodos: asignar directamente a a.shape modifica el arreglo a en su lugar; mientras que a.reshape(3, 2) devuelve un nuevo objeto de arreglo (normalmente comparte los mismos datos con a), y a permanece sin cambios.
ndarray.size
ndarray.size devuelve el número total de elementos del arreglo, igual al producto de los tamaños de cada eje en shape.
Ejemplo
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape) # El shape es (2, 3)
print(a.size) # Número total de elementos: 2 × 3 = 6
El resultado es:
(2, 3) 6
ndarray.dtype
ndarray.dtype devuelve el tipo de datos de los elementos del arreglo.
El objeto dtype contiene información como el nombre del tipo y el ancho de bits de los elementos; por ejemplo, int64 indica enteros de 64 bits, float32 indica flotantes de 32 bits.
Ejemplo
# Una lista de enteros crea por defecto un arreglo int64 (en Windows el valor predeterminado es int32)
a = np.array([1, 2, 3])
print(a.dtype)
# Al crear, se puede especificar explícitamente el tipo de datos con el parámetro dtype
b = np.array([1, 2, 3], dtype=np.float32)
print(b.dtype)
El resultado es:
int64 float32
ndarray.real y ndarray.imag
ndarray.real y ndarray.imag devuelven respectivamente la parte real e imaginaria de cada elemento del arreglo; se usan principalmente cuando el tipo de los elementos es complejo (complex).
Ejemplo
# Crear un arreglo de números complejos; el tipo predeterminado es complex128
a = np.array([1+2j, 3+4j, 5+6j])
print(a.real) # La parte real de cada elemento
print(a.imag) # La parte imaginaria de cada elemento
El resultado es:
[1. 3. 5.] [2. 4. 6.]
ndarray.itemsize
ndarray.itemsize devuelve el tamaño de cada elemento del arreglo en bytes.
Por ejemplo, en un arreglo con elementos de tipo float64, el valor del atributo itemsize es 8 (float64 ocupa 64 bits; cada 8 bits son 1 byte, 64 ÷ 8 = 8 bytes).
Del mismo modo, en un arreglo con elementos de tipo int32, el valor de itemsize es 4 (32 ÷ 8).
El producto de size e itemsize es el número total de bytes que ocupan los datos del arreglo, es decir, el valor del atributo ndarray.nbytes.
Ejemplo
# El dtype del arreglo es int8; cada elemento ocupa 1 byte
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)
# El dtype del arreglo es float64; cada elemento ocupa 8 bytes
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)
El resultado es:
1 8
ndarray.flags
ndarray.flags devuelve la información de memoria del objeto ndarray e incluye las siguientes propiedades:
| Atributo | Descripción |
|---|---|
| C_CONTIGUOUS (C) | Los datos están en una única región de memoria contigua de estilo C |
| F_CONTIGUOUS (F) | Los datos están en una única región de memoria contigua de estilo Fortran |
| OWNDATA (O) | El arreglo es dueño de la memoria que utiliza, no la toma prestada de otros objetos |
| WRITEABLE (W) | La región de datos se puede escribir; si se establece este valor en False, los datos son de solo lectura |
| ALIGNED (A) | Los datos y todos los elementos están alineados adecuadamente con el hardware |
| WRITEBACKIFCOPY (X) | Este arreglo es una copia de otro arreglo; cuando este arreglo se libera, su contenido se escribe de vuelta en el arreglo original |
El antiguo UPDATEIFCOPY (U) es el nombre anterior de WRITEBACKIFCOPY; fue obsoleto en NumPy 1.14 y eliminado por completo desde NumPy 2.0, por lo que ya no debería usarse.
C_CONTIGUOUS y F_CONTIGUOUS describen el orden de disposición de los mismos datos en la memoria; un mismo arreglo bidimensional tiene dos formas típicas de almacenarse:
Ejemplo
x = np.array([1, 2, 3, 4, 5])
print(x.flags)
El resultado de salida es:
C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : True WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : FalseOtras extensiones