You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中实现类似numpy.random.choice的行级概率采样

Polars实现每行按概率采样(类似numpy.random.choice)

在NumPy中,我们可以通过np.random.choice指定概率分布采样单个值:

import numpy as np

# 可选结果
values = [0, 1, 2, 3, 4]
# 对应概率
probabilities = [0.15, 0.30, 0.25, 0.20, 0.10]

# 按概率采样
sampled_value = np.random.choice(values, p=probabilities)
print(sampled_value)

但如果是Polars DataFrame,每行都有对应不同结果的概率列(如下示例),需要为每行生成一个按该行概率采样的结果列sampled_goal,可以用以下两种方式实现:

示例DataFrame

import polars as pl

df = pl.DataFrame({
    "id": [1, 2, 3],
    "prob_0": [0.1, 0.2, 0.15],
    "prob_1": [0.3, 0.25, 0.35],
    "prob_2": [0.25, 0.3, 0.25],
    "prob_3": [0.2, 0.15, 0.15],
    "prob_4": [0.15, 0.1, 0.1]
})

方法1:逐行处理(简单直观)

通过pl.struct打包每行的概率列,再用map_elements调用np.random.choice逐行采样:

def sample_row(probs):
    return np.random.choice([0,1,2,3,4], p=list(probs.values()))

df = df.with_columns(
    sampled_goal=pl.struct(pl.col("prob_*")).map_elements(sample_row, return_dtype=pl.Int64)
)

print(df)

注意:这种方法逻辑简单,但map_elements是逐行执行,大数据集下效率较低。

方法2:向量化处理(高效)

利用Polars的向量化操作,结合累积概率和随机数实现高效采样:

values = [0,1,2,3,4]
prob_cols = [f"prob_{v}" for v in values]

df = df.with_columns(
    # 为每行生成一个0-1之间的随机数
    rand=pl.float_rand(seed=42),
    # 将概率列转为列表并计算累积和
    cum_probs=pl.concat_list(prob_cols).list.cum_sum(),
    # 生成对应结果值的列表(每行重复一次)
    value_list=pl.lit(values).repeat(pl.count())
).with_columns(
    # 找到第一个累积和大于随机数的索引,取对应结果值
    sampled_goal=pl.col("cum_probs")
    .list.eval(pl.element() > pl.col("rand"))
    .list.arg_true().first()
    .list.get(pl.col("value_list"))
).drop(["rand", "cum_probs", "value_list"])  # 删除临时列

print(df)

这种方法大部分操作是向量化执行,适合处理大规模数据集。

内容的提问来源于stack exchange,提问作者Pedro_Siqueira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:01:09