NumPy Linspace: Cómo crear arrays uniformemente espaciados en Python
Updated on
Generar una secuencia de números uniformemente espaciados parece trivial hasta que necesitas control exacto sobre el inicio, el fin y la cantidad. La función integrada range() de Python solo maneja enteros, e incluso numpy.arange() puede producir sorpresas de tipo off-by-one cuando los tamaños de paso con punto flotante acumulan errores de redondeo. Si alguna vez graficaste una función y obtuviste una curva irregular o perdiste el último valor de x, te encontraste exactamente con este problema. numpy.linspace() existe para resolverlo: especificas cuántos puntos quieres entre dos extremos, y NumPy calcula el espaciado exacto por ti.
En esta guía, aprenderás la API completa de np.linspace(), verás comparaciones lado a lado con np.arange(), y recorrerás casos de uso reales, desde graficar curvas suaves hasta construir mallas multidimensionales. Cada ejemplo de código está listo para copiar y pegar, y muestra su salida.
¿Qué hace np.linspace()?
numpy.linspace() devuelve un array de números uniformemente espaciados sobre un intervalo especificado. La idea clave es que defines el número de muestras en lugar del tamaño del paso.
Firma completa
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
start | float o array-like | requerido | Inicio del intervalo |
stop | float o array-like | requerido | Fin del intervalo |
num | int | 50 | Número de muestras a generar |
endpoint | bool | True | Si se incluye stop en la salida |
retstep | bool | False | Si es True, también devuelve el tamaño del paso |
dtype | dtype | None | Tipo de datos del array de salida (se infiere si es None) |
axis | int | 0 | Eje a lo largo del cual almacenar las muestras (relevante cuando start/stop son arrays) |
Ejemplo básico
import numpy as np
arr = np.linspace(0, 1, 5)
print(arr)
# Output: [0. 0.25 0.5 0.75 1. ]NumPy divide el intervalo [0, 1] en 4 espacios iguales (uno menos que los 5 puntos solicitados) y devuelve los cinco valores límite, incluyendo ambos extremos.
Controlando el número de puntos con num
El parámetro num determina cuántos valores hay en el array devuelto. El valor predeterminado es 50, por lo que llamar a np.linspace(0, 10) te da 50 valores aunque no los hayas pedido explícitamente.
import numpy as np
# 3 puntos entre 0 y 10
print(np.linspace(0, 10, num=3))
# Output: [ 0. 5. 10.]
# 6 puntos entre -1 y 1
print(np.linspace(-1, 1, num=6))
# Output: [-1. -0.6 -0.2 0.2 0.6 1. ]Un error común es establecer num=1. En ese caso, solo se devuelve el valor start.
import numpy as np
print(np.linspace(0, 10, num=1))
# Output: [0.]El parámetro endpoint: Incluir o excluir el valor de parada
Por defecto, endpoint=True, lo que significa que el valor stop es el último elemento del array. Cuando estableces endpoint=False, el valor de parada se excluye y el espaciado cambia.
import numpy as np
with_endpoint = np.linspace(0, 1, 5, endpoint=True)
print("endpoint=True: ", with_endpoint)
# Output: endpoint=True: [0. 0.25 0.5 0.75 1. ]
without_endpoint = np.linspace(0, 1, 5, endpoint=False)
print("endpoint=False:", without_endpoint)
# Output: endpoint=False: [0. 0.2 0.4 0.6 0.8]| Configuración | Fórmula para el paso | Último valor |
|---|---|---|
endpoint=True | (stop - start) / (num - 1) | Exactamente stop |
endpoint=False | (stop - start) / num | Un paso antes de stop |
¿Cuándo es útil endpoint=False? Un ejemplo clásico es generar ángulos para una transformada discreta de Fourier, donde necesitas N puntos en [0, 2*pi) sin repetir el ángulo inicial.
import numpy as np
N = 8
angles = np.linspace(0, 2 * np.pi, N, endpoint=False)
print(np.round(angles, 4))
# Output: [0. 0.7854 1.5708 2.3562 3.1416 3.927 4.7124 5.4978]Obtener el tamaño del paso con retstep
Cuando retstep=True, np.linspace() devuelve una tupla: el array y el tamaño del paso calculado. Esto es útil cuando necesitas el espaciado para cálculos posteriores sin calcularlo tú mismo.
import numpy as np
values, step = np.linspace(0, 10, num=5, retstep=True)
print("Values:", values)
print("Step: ", step)
# Output:
# Values: [ 0. 2.5 5. 7.5 10. ]
# Step: 2.5Puedes usar el tamaño del paso para diferenciación numérica, integración, o simplemente para verificar que tu malla tiene la resolución que esperas.
import numpy as np
x, dx = np.linspace(0, np.pi, 1000, retstep=True)
# Approximate integral of sin(x) from 0 to pi using the trapezoidal rule
integral = np.trapz(np.sin(x), dx=dx)
print(f"Integral of sin(x) over [0, pi]: {integral:.6f}")
# Output: Integral of sin(x) over [0, pi]: 2.000000np.linspace() vs np.arange(): Cuándo usar cada una
Ambas funciones crean secuencias de números, pero difieren de manera fundamental: linspace te permite especificar la cantidad, mientras que arange te permite especificar el tamaño del paso.
| Característica | np.linspace() | np.arange() |
|---|---|---|
| Tú especificas | Número de puntos (num) | Tamaño del paso (step) |
| ¿Endpoint incluido? | Sí por defecto | Nunca (stop exclusivo) |
| Precisión de paso flotante | Exacta (divide el intervalo) | Puede acumular error de redondeo |
| Uso típico | Graficación, interpolación | Rangos enteros, iteración |
| ¿Devuelve tamaño de paso? | Sí, via retstep=True | No (ya lo conoces) |
Trampa de punto flotante con arange
import numpy as np
# arange can produce unexpected element counts with float steps
arr = np.arange(0, 1, 0.1)
print(len(arr), arr)
# Output: 10 [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
# Slightly different bounds can cause an extra element
arr2 = np.arange(0, 1.0 + 1e-15, 0.1)
print(len(arr2))
# Output: 11Con linspace, siempre obtienes exactamente el número de elementos que pediste. Al trabajar con intervalos de punto flotante, prefiere linspace a menos que genuinamente necesites un tamaño de paso específico y límites compatibles con enteros.
Casos de uso prácticos
1. Graficar curvas suaves
El uso más común de np.linspace() es generar valores x para graficar funciones matemáticas. Más puntos producen curvas más suaves.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-2 * np.pi, 2 * np.pi, 300)
y = np.sin(x) / x # sinc-like function (warning: division by zero at x=0)
# Handle division by zero
y = np.where(np.isclose(x, 0), 1.0, np.sin(x) / x)
plt.figure(figsize=(8, 4))
plt.plot(x, y, linewidth=1.5)
plt.title("sinc-like function: sin(x)/x")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("sinc_plot.png", dpi=100)
plt.show()2. Procesamiento de señales: Generar ejes temporales
Al simular o analizar señales, necesitas un vector temporal con una tasa de muestreo conocida. linspace lo hace sencillo.
import numpy as np
duration = 1.0 # seconds
sample_rate = 44100 # Hz (CD quality)
num_samples = int(duration * sample_rate)
t = np.linspace(0, duration, num_samples, endpoint=False)
# Generate a 440 Hz sine wave (concert A)
frequency = 440
signal = np.sin(2 * np.pi * frequency * t)
print(f"Time array shape: {t.shape}")
print(f"First 5 time values: {t[:5]}")
print(f"First 5 signal values: {np.round(signal[:5], 6)}")
# Output:
# Time array shape: (44100,)
# First 5 time values: [0.00000000e+00 2.26757370e-05 4.53514739e-05 6.80272109e-05 9.07029478e-05]
# First 5 signal values: [0. 0.062648 0.125178 0.187474 0.24942 ]Observa que aquí se usa endpoint=False porque la señal es periódica: la muestra en t = 1.0 duplicaría la muestra en t = 0.0.
3. Crear gradientes de color
linspace es útil para interpolar entre valores de color al construir mapas de color personalizados.
import numpy as np
# Interpolate between blue (0, 0, 255) and red (255, 0, 0) in 5 steps
steps = 5
r = np.linspace(0, 255, steps).astype(int)
g = np.zeros(steps, dtype=int)
b = np.linspace(255, 0, steps).astype(int)
colors = np.column_stack([r, g, b])
for i, c in enumerate(colors):
print(f"Step {i}: RGB({c[0]:3d}, {c[1]:3d}, {c[2]:3d})")
# Output:
# Step 0: RGB( 0, 0, 255)
# Step 1: RGB( 63, 0, 191)
# Step 2: RGB(127, 0, 127)
# Step 3: RGB(191, 0, 63)
# Step 4: RGB(255, 0, 0)Mallas multidimensionales con linspace y meshgrid
Para cálculos en 2D o 3D (mapas de calor, gráficos de superficie, gráficos de contorno), combina np.linspace() con np.meshgrid().
import numpy as np
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
# Compute a 2D Gaussian
Z = np.exp(-(X**2 + Y**2))
print(f"X shape: {X.shape}")
print(f"Z min: {Z.min():.6f}, Z max: {Z.max():.6f}")
# Output:
# X shape: (100, 100)
# Z min: 0.000001, Z max: 1.000000import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + Y**2))
plt.figure(figsize=(6, 5))
plt.contourf(X, Y, Z, levels=20, cmap="viridis")
plt.colorbar(label="Amplitude")
plt.title("2D Gaussian via linspace + meshgrid")
plt.xlabel("x")
plt.ylabel("y")
plt.tight_layout()
plt.savefig("gaussian_contour.png", dpi=100)
plt.show()Este patrón se escala a cualquier dimensión. Para mallas 3D, agrega una tercera llamada a linspace y usa np.meshgrid(x, y, z).
El parámetro dtype
Por defecto, np.linspace() devuelve valores float64. Puedes anular esto con el parámetro dtype, aunque ten en cuenta que los tipos enteros truncarán los valores calculados.
import numpy as np
# Float64 (default)
print(np.linspace(0, 5, 6).dtype)
# Output: float64
# Explicit float32 for memory savings
arr32 = np.linspace(0, 1, 5, dtype=np.float32)
print(arr32, arr32.dtype)
# Output: [0. 0.25 0.5 0.75 1. ] float32
# Integer dtype truncates values
arr_int = np.linspace(0, 10, 5, dtype=int)
print(arr_int)
# Output: [ 0 2 5 7 10]Al usar tipos de datos enteros, las partes fraccionarias simplemente se descartan (comportamiento floor), lo que puede producir resultados con espaciado desigual. Mantén los tipos float a menos que tengas una razón específica para convertir.
Patrones comunes: Generar valores X para graficación de funciones
Aquí tienes una referencia concisa de patrones que usarás repetidamente.
Patrón 1: Gráfico de función estándar
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 500)
plt.plot(x, np.sin(x), label="sin(x)")
plt.plot(x, np.cos(x), label="cos(x)")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()Patrón 2: Curva paramétrica
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(0, 2 * np.pi, 1000)
x = 16 * np.sin(t)**3
y = 13 * np.cos(t) - 5 * np.cos(2*t) - 2 * np.cos(3*t) - np.cos(4*t)
plt.figure(figsize=(5, 5))
plt.plot(x, y, color="red")
plt.title("Heart Curve")
plt.axis("equal")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()Patrón 3: Evaluar un polinomio sobre un rango
import numpy as np
coefficients = [1, -3, 2] # x^2 - 3x + 2
x = np.linspace(-1, 4, 6)
y = np.polyval(coefficients, x)
for xi, yi in zip(x, y):
print(f"x={xi:5.2f} -> y={yi:5.2f}")
# Output:
# x=-1.00 -> y= 6.00
# x= 0.00 -> y= 2.00
# x= 1.00 -> y= 0.00
# x= 2.00 -> y= 0.00
# x= 3.00 -> y= 2.00
# x= 4.00 -> y= 6.00Visualizar datos generados con Linspace usando PyGWalker
Cuando trabajas con arrays creados por np.linspace(), a menudo necesitas explorar los datos resultantes de forma interactiva: ajustar ejes, filtrar rangos o comparar múltiples series sin reescribir el código de graficación cada vez. PyGWalker (opens in a new tab) es una biblioteca Python de código abierto que convierte cualquier DataFrame de Pandas en una interfaz de visualización interactiva similar a Tableau directamente dentro de Jupyter Notebook.
Así es como combinar datos generados con linspace con PyGWalker para exploración interactiva:
import numpy as np
import pandas as pd
import pygwalker as pyg
# Generate data using linspace
x = np.linspace(0, 4 * np.pi, 200)
df = pd.DataFrame({
"x": x,
"sin": np.sin(x),
"cos": np.cos(x),
"damped_sin": np.exp(-0.1 * x) * np.sin(x),
})
# Launch interactive visualization in Jupyter
walker = pyg.walk(df)Con PyGWalker abierto, puedes arrastrar x al eje x, soltar sin y damped_sin en el eje y, y comparar formas de onda al instante. Puedes cambiar entre gráficos de líneas, gráficos de dispersión y gráficos de barras sin escribir código adicional. Esto es especialmente útil cuando generas datos a través de diferentes rangos de parámetros con linspace y quieres confirmar visualmente el comportamiento antes de comprometerte con un gráfico final.
Preguntas frecuentes
¿Cuál es la diferencia entre np.linspace y np.arange?
np.linspace() toma un valor de inicio, valor de parada y el número de puntos que deseas. np.arange() toma un valor de inicio, valor de parada y un tamaño de paso. Usa linspace cuando te importa cuántos puntos obtienes (graficación, interpolación). Usa arange cuando te importa el paso exacto entre valores (secuencias enteras, bucles).
¿np.linspace incluye el endpoint por defecto?
Sí. Por defecto, endpoint=True, lo que significa que el valor stop se incluye como último elemento. Establece endpoint=False para excluirlo, lo cual es útil para señales periódicas o transformadas de Fourier.
¿Cómo obtengo el tamaño del paso de np.linspace?
Pasa retstep=True para obtener una tupla de (array, tamaño_del_paso). Por ejemplo: values, step = np.linspace(0, 10, 100, retstep=True).
¿Puede np.linspace generar enteros?
Puedes pasar dtype=int, pero los valores se truncarán (no se redondearán), lo que a menudo produce un espaciado desigual. Si necesitas enteros uniformemente espaciados, np.arange() es generalmente una mejor opción.
¿Cuántos puntos debo usar para un gráfico suave?
Para la mayoría de los gráficos de funciones 2D, de 200 a 500 puntos producen curvas visualmente suaves. Para funciones de alta frecuencia o figuras de calidad de publicación, 1000 puntos es una opción segura. Más puntos aumentan el uso de memoria y el tiempo de renderizado, así que equilibra la suavidad con el rendimiento.
Conclusión
numpy.linspace() es una de las funciones de NumPy más utilizadas por una buena razón: te da control preciso sobre cuántos valores uniformemente espaciados generas entre dos extremos. A diferencia de np.arange(), nunca te sorprende con un elemento extra o faltante debido al redondeo de punto flotante. Los parámetros endpoint, retstep y dtype te dan control detallado para todo, desde gráficos rápidos hasta pipelines de procesamiento de señales.
Puntos clave:
- Usa
numpara establecer el número exacto de valores de salida. - Establece
endpoint=Falsepara datos periódicos donde el valor de parada duplicaría el inicio. - Usa
retstep=Truesiempre que necesites el tamaño del paso para cálculos posteriores. - Prefiere
linspacesobrearangepara intervalos de punto flotante. - Combina
linspaceconmeshgridpara mallas multidimensionales.
Con estos patrones en tu kit de herramientas, puedes generar secuencias numéricas con confianza para graficación, simulación, interpolación y computación científica en Python.