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 = 1: flecha en dirección horizontal axis = 1 (eje 1) Dirección horizontal, a lo largo de cada fila axis = 0: flecha en dirección vertical axis = 0 (eje 0) Dirección vertical, a lo largo de cada columna Índice de columna Columna 0 Columna 1 Columna 2 Índice de fila Fila 0 Fila 1 Rejilla de 2×3 1 2 3 4 5 6 Línea discontinua que asocia las filas con la tarjeta de shape Tarjeta explicativa de shape shape = (2, 3) 2 → longitud del eje 0 (número de filas) 3 → longitud del eje 1 (número de columnas) Resumen de propiedades en la parte inferior ndim = 2 (número de ejes, es decir, el rango) · size = 2 × 3 = 6 (número total de elementos)

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

import numpy as np

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:

↓↓↓
1
2
3
4
5
6
5
7
9
→
6
→
15
a.sum(axis=0) → [5 7 9], comprime los elementos de cada columna en un solo número a lo largo del eje 0

Las propiedades más importantes del objeto ndarray en NumPy son:

AtributoDescripción
ndarray.ndimRango (rank) del arreglo, es decir, el número de dimensiones o ejes del arreglo.
ndarray.shapeDimensiones 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.sizeEl número total de elementos del arreglo, igual alndarray.shapeproducto de los tamaños de cada eje en shape.
ndarray.dtypeEl tipo de datos de los elementos del arreglo.
ndarray.itemsizeEl tamaño de cada elemento del arreglo, en bytes.
ndarray.flagsContiene información sobre la disposición en memoria, como si es contigua en C o Fortran, si es de solo lectura, etc.
ndarray.realLa parte real de cada elemento del arreglo (si el tipo de elemento es complejo).
ndarray.imagLa parte imaginaria de cada elemento del arreglo (si el tipo de elemento es complejo).
ndarray.dataEl 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

import numpy as np

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

import numpy as np

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

import numpy as np

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

import numpy as np

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

import numpy as np

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

import numpy as np

# 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

import numpy as np

# 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

import numpy as np

# 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:

AtributoDescripció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:

Izquierda: estilo C (orden por filas) Estilo C (orden por filas) Primero se almacena la fila 0, luego la fila 1 123 456 Índices de orden de almacenamiento: por filas 1~6 1 2 3 4 5 6 Expandir secuencialmente por filas Memoria: 1 2 3 4 5 6 123 456 1 2 3 4 5 6 012 345 Direcciones de memoria (de izquierda a derecha) C_CONTIGUOUS : True Derecha: estilo Fortran (orden por columnas) Estilo Fortran (orden por columnas) Primero se almacena la columna 0, luego la columna 1 123 456 Índices de orden de almacenamiento: por columnas 1~6 1 2 3 4 5 6 Expandir secuencialmente por columnas Memoria: 1 4 2 5 3 6 142 536 1 2 3 4 5 6 012 345 Direcciones de memoria (de izquierda a derecha) F_CONTIGUOUS : True Nota al pie Los arreglos de NumPy se almacenan de forma predeterminada en estilo C (orden por filas)

Ejemplo

import numpy as np

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 : False
Otras extensiones