NumPy Linspace:如何在 Python 中创建等间距数组
Updated on
生成一个等间距的数字序列看起来很简单,直到你需要精确控制起始值、终止值和数量时才发现并非如此。Python 内置的 range() 只能处理整数,而 numpy.arange() 在浮点步长累积舍入误差时也可能产生意外结果。如果你曾经绘制函数图像时得到锯齿状曲线或丢失了最后一个 x 值,那你就遇到了这个问题。numpy.linspace() 正是为解决这个问题而存在的:你只需指定两个端点之间需要多少个点,NumPy 就会为你计算精确的间距。
在本指南中,你将学习完整的 np.linspace() API,看到它与 np.arange() 的对比,并通过实际用例——从绘制平滑曲线到构建多维网格——进行实践。每个代码示例都可以直接复制粘贴运行,并展示其输出结果。
np.linspace() 做什么?
numpy.linspace() 返回指定区间内等间距数字的数组。核心思想是你定义样本数量而不是步长。
完整签名
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
start | float 或 array-like | 必需 | 区间的起始值 |
stop | float 或 array-like | 必需 | 区间的终止值 |
num | int | 50 | 要生成的样本数量 |
endpoint | bool | True | 是否在输出中包含 stop |
retstep | bool | False | 如果为 True,还返回步长 |
dtype | dtype | None | 输出数组的数据类型(None 时自动推断) |
axis | int | 0 | 存储样本的轴(当 start/stop 为数组时相关) |
基本示例
import numpy as np
arr = np.linspace(0, 1, 5)
print(arr)
# Output: [0. 0.25 0.5 0.75 1. ]NumPy 将区间 [0, 1] 分成 4 个等间距(比请求的 5 个点少 1 个),并返回所有五个边界值,包括两个端点。
使用 num 控制点的数量
num 参数决定返回数组中有多少个值。默认值是 50,因此调用 np.linspace(0, 10) 即使你没有明确指定,也会给你 50 个值。
import numpy as np
# 0 到 10 之间的 3 个点
print(np.linspace(0, 10, num=3))
# Output: [ 0. 5. 10.]
# -1 到 1 之间的 6 个点
print(np.linspace(-1, 1, num=6))
# Output: [-1. -0.6 -0.2 0.2 0.6 1. ]一个常见的错误是设置 num=1。在这种情况下,只返回 start 值。
import numpy as np
print(np.linspace(0, 10, num=1))
# Output: [0.]endpoint 参数:包含或排除终止值
默认情况下 endpoint=True,意味着 stop 值是数组的最后一个元素。当你设置 endpoint=False 时,终止值被排除,间距也会改变。
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]| 设置 | 步长公式 | 最后一个值 |
|---|---|---|
endpoint=True | (stop - start) / (num - 1) | 恰好是 stop |
endpoint=False | (stop - start) / num | stop 前一步 |
endpoint=False 什么时候有用?一个经典的例子是为离散傅里叶变换生成角度,你需要在 [0, 2*pi) 中取 N 个点而不重复起始角度。
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]使用 retstep 获取步长
当 retstep=True 时,np.linspace() 返回一个元组:数组和计算得到的步长。当你需要间距用于后续计算而不想自己计算时,这很方便。
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.5你可以将步长用于数值微分、积分,或者简单地验证网格是否具有预期的分辨率。
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() 与 np.arange():何时使用哪个
两个函数都创建数字序列,但它们有根本区别:linspace 让你指定数量,而 arange 让你指定步长。
| 特性 | np.linspace() | np.arange() |
|---|---|---|
| 你指定的 | 点的数量(num) | 步长(step) |
| 包含端点? | 默认是 | 从不(排他性 stop) |
| 浮点步长精度 | 精确(等分区间) | 可能累积舍入误差 |
| 典型用途 | 绘图、插值 | 整数范围、迭代 |
| 返回步长? | 是,通过 retstep=True | 否(你已经知道了) |
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: 11使用 linspace,你总是能得到精确数量的元素。处理浮点区间时,除非你确实需要特定的步长和整数友好的边界,否则应优先选择 linspace。
实际用例
1. 绘制平滑曲线
np.linspace() 最常见的用途是为绘制数学函数生成 x 值。更多的点产生更平滑的曲线。
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. 信号处理:生成时间轴
在模拟或分析信号时,你需要一个具有已知采样率的时间向量。linspace 使这变得简单直接。
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 ]注意这里使用了 endpoint=False,因为信号是周期性的:t = 1.0 处的采样点会与 t = 0.0 处的采样点重复。
3. 创建颜色渐变
linspace 在构建自定义颜色映射时用于在颜色值之间进行插值非常有用。
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)使用 linspace 和 meshgrid 创建多维网格
对于 2D 或 3D 计算(热力图、曲面图、等高线图),将 np.linspace() 与 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()这个模式可以扩展到任意维度。对于 3D 网格,添加第三个 linspace 调用并使用 np.meshgrid(x, y, z)。
dtype 参数
默认情况下,np.linspace() 返回 float64 类型的值。你可以使用 dtype 参数覆盖此设置,但要注意整数类型会截断计算值。
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]使用整数 dtype 时,小数部分会被直接丢弃(向下取整行为),这可能产生间距不均的结果。除非有特定的转换理由,否则请保持使用浮点类型。
常见模式:为函数绘图生成 X 值
以下是你会反复使用的模式的简洁参考。
模式 1:标准函数图
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()模式 2:参数曲线
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()模式 3:在范围上求多项式值
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.00使用 PyGWalker 可视化 Linspace 生成的数据
在处理由 np.linspace() 创建的数组时,你经常需要交互式地探索结果数据——调整坐标轴、过滤范围或比较多个系列,而无需每次都重写绘图代码。PyGWalker (opens in a new tab) 是一个开源 Python 库,可以将任何 Pandas DataFrame 转换为类似 Tableau 的交互式可视化界面,直接在 Jupyter Notebook 中使用。
以下是将 linspace 生成的数据与 PyGWalker 结合进行交互式探索的方法:
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)打开 PyGWalker 后,你可以将 x 拖到 x 轴,将 sin 和 damped_sin 放到 y 轴上,即时比较波形。你可以在折线图、散点图和柱状图之间切换,无需编写额外代码。当你使用 linspace 在不同参数范围内生成数据,并希望在确定最终图表之前直观地确认行为时,这尤其有用。
常见问题
np.linspace 和 np.arange 有什么区别?
np.linspace() 接收起始值、终止值和你想要的点数。np.arange() 接收起始值、终止值和步长。当你关心获得多少个点时(绘图、插值)使用 linspace。当你关心值之间的精确步长时(整数序列、循环)使用 arange。
np.linspace 默认包含端点吗?
是的。默认 endpoint=True,这意味着 stop 值作为最后一个元素被包含。设置 endpoint=False 来排除它,这对周期性信号或傅里叶变换很有用。
如何从 np.linspace 获取步长?
传入 retstep=True 以获得 (数组, 步长) 的元组。例如:values, step = np.linspace(0, 10, 100, retstep=True)。
np.linspace 能生成整数吗?
你可以传入 dtype=int,但值会被截断(而非四舍五入),这通常会产生不均匀的间距。如果你需要均匀间隔的整数,np.arange() 通常是更好的选择。
平滑图表应该使用多少个点?
对于大多数 2D 函数图,200 到 500 个点就能产生视觉上平滑的曲线。对于高频函数或出版质量的图表,1000 个点是安全的选择。更多的点会增加内存使用和渲染时间,因此需要在平滑度和性能之间取得平衡。
总结
numpy.linspace() 是最常用的 NumPy 函数之一,原因很充分:它让你精确控制在两个端点之间生成多少个等间距的值。与 np.arange() 不同,它永远不会因为浮点舍入而产生多余或缺少的元素。endpoint、retstep 和 dtype 参数为你提供了从快速绘图到信号处理流水线的精细控制。
关键要点:
- 使用
num设置精确的输出值数量。 - 对于终止值会与起始值重复的周期性数据,设置
endpoint=False。 - 当需要步长用于后续计算时,使用
retstep=True。 - 对于浮点区间,优先选择
linspace而非arange。 - 将
linspace与meshgrid结合使用以创建多维网格。
掌握了这些模式,你就可以自信地在 Python 中为绘图、模拟、插值和科学计算生成数值序列了。