Skip to content
话题
NumPy
NumPy Linspace:如何在 Python 中创建等间距数组

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)
参数类型默认值描述
startfloat 或 array-like必需区间的起始值
stopfloat 或 array-like必需区间的终止值
numint50要生成的样本数量
endpointboolTrue是否在输出中包含 stop
retstepboolFalse如果为 True,还返回步长
dtypedtypeNone输出数组的数据类型(None 时自动推断)
axisint0存储样本的轴(当 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) / numstop 前一步

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.000000

np.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.000000
import 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 轴,将 sindamped_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() 不同,它永远不会因为浮点舍入而产生多余或缺少的元素。endpointretstepdtype 参数为你提供了从快速绘图到信号处理流水线的精细控制。

关键要点:

  • 使用 num 设置精确的输出值数量。
  • 对于终止值会与起始值重复的周期性数据,设置 endpoint=False
  • 当需要步长用于后续计算时,使用 retstep=True
  • 对于浮点区间,优先选择 linspace 而非 arange
  • linspacemeshgrid 结合使用以创建多维网格。

掌握了这些模式,你就可以自信地在 Python 中为绘图、模拟、插值和科学计算生成数值序列了。

📚