当前位置: 首页 > 图灵资讯 > 行业资讯> 怎么在Python中实现NumPy数组的无放回高效随机抽样

怎么在Python中实现NumPy数组的无放回高效随机抽样

来源:图灵python
时间: 2026-09-02 16:13:13
最可靠的方法是使用numpy.random.Generator.choice:RNG需要先创建 = np.random.default_rng(seed)例子,再次调用rng.choice(arr, size, replace=False),性能优异,可复制,线程安全,不支持隐式多维输入,轴向抽样或平整必须手动处理。

numpy.random.Generator.choice 这是目前最可靠的方式

NumPy 1.17+ 弃用了旧的 numpy.random.choice(来自全局 np.random 基于模块的推荐使用) Generator 新界面。默认情况下,没有放回抽样,底部使用 Fisher-Yates 变体洗牌,性能好,可复制,线程安全。

直接调用常见错误 np.random.choice(a, size, replace=False) —— 这在 NumPy ≥1.25 中会触发 DeprecationWarning,随机种子粒度无法控制。

  • 必须先创建 Generator 实例:rng = np.random.default_rng(seed=42)
  • 抽样时输入数组本身(而不是长度):rng.choice(arr, size=10, replace=False)arr 可以是 1D 数组或任何可能的索引序列
  • arr 它是多维的,需要先展平或使用 np.take + 随机索引配合,choice 不支持高维数组直接轴向无放回采样
在接近数组长度时,应注意内存和性能

size 接近 len(arr)(比如 > 70%),replace=False 内部会退化为洗牌后的切片(即先退化为洗牌后的切片) shuffle 整个数组再次取前 size (1)这将额外分配等长内存并修改原始数组副本。

如果你只想“打乱后取前” k 个”,更有效的方法是直接 shuffle 再切片:

立即学习“Python免费学习笔记(深入);

rng = np.random.default_rng(42)
shuffled = arr.copy()
rng.shuffle(shuffled)
sample = shuffled[:k]

这样就避免了 choice 特别是在大数组和高比例采样中,中间索引映射费用很快 2–3 而且显式可控。

Python数据分析助手

为业务和科研数据的快速处理提供Python数据清理、统计分析和可视化建议。

下载

手动结构索引二维数组按行/列无放回抽样

Generator.choice 只接受一维输入,不能直接写 rng.choice(matrix, axis=0, replace=False) —— 这会报错 ValueError: a must be 1-dimensional

正确的方法是生成行/列索引,然后用高级索引提取:

  • 按行抽样(随机选择) 5 行):rows = rng.choice(matrix.shape[0], size=5, replace=False); sample = matrix[rows]
  • 按列抽样(随机选择) 3 列):cols = rng.choice(matrix.shape[1], size=3, replace=False); sample = matrix[:, cols]
  • 注意:这里 choice 作用于整数范围,而不是原始数组,因此不会触发复制整个数据的费用
检查旧代码迁移情况 replace 默认值和 seed 行为

老写法 np.random.choice(arr, 10) 默认 replace=True;而新 Generator.choice **没有默认 replace 值**,必须显式传参,否则报告 TypeError

另外,np.random.seed() 全局影响所有后续调用,但是 default_rng(seed) 在多线程或单元测试中,这是一个局部实例,不相互干扰——这一点尤为关键。泄漏会导致随机污染。

最容易被忽视的是,如果原始逻辑依赖 np.random.choice 隐藏非一维数组 ravel 行为(如传入) list of lists),新界面将直接报错,必须提前报错 np.asarray(...).ravel()