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

如何在Polars中为满足布尔条件的行用列表值创建新列?

在Polars DataFrame中按条件用列表填充新列

我想在Polars DataFrame中创建一个新列,仅在满足特定条件的行中用现有列表填充值,同时保持总行数不变。

示例数据如下:

import polars as pl

df = pl.DataFrame({
    'cond1': [-1, 0, 1, 2, 2, 3, 4, 5],
    'cond2': ['No', 'No', 'No', 'Yes','Yes', 'Yes', 'Yes', 'Yes']
})

我知道在Pandas中可以这样实现(列表长度与筛选后的行数一致,output为新列):

df_pd = df.to_pandas()

conditions = ((df_pd['cond1']>=1) & (df_pd['cond2'] == 'Yes'))
list_new = [1,2,3,4,5]

df_pd.loc[conditions, 'output'] = list_new

执行后结果:

#    cond1 cond2  output
# 0     -1    No     NaN
# 1      0    No     NaN
# 2      1    No     NaN
# 3      2   Yes     1.0
# 4      2   Yes     2.0
# 5      3   Yes     3.0
# 6      4   Yes     4.0
# 7      5   Yes     5.0

请问如何在Polars中实现相同功能?我尝试过以下代码的多种变体但均未成功:

df = df.with_columns(pl.when(conditions).then(list_new).alias('output'))

解决方案

Polars中不能直接在pl.when(...).then(...)里传入Python列表(then要求接收列表达式,而非逐行赋值的列表),可以通过以下两种方式实现需求:

方法一:索引匹配+左连接

先筛选出符合条件的行并赋值,再通过原表索引与筛选表左连接,保留所有行:

import polars as pl

df = pl.DataFrame({
    'cond1': [-1, 0, 1, 2, 2, 3, 4, 5],
    'cond2': ['No', 'No', 'No', 'Yes','Yes', 'Yes', 'Yes', 'Yes']
})

list_new = [1,2,3,4,5]
cond = (pl.col('cond1') >= 1) & (pl.col('cond2') == 'Yes')

# 给符合条件的行添加output列,并保留原索引
filtered_df = df.filter(cond).with_columns(
    pl.Series(list_new).alias('output')
).with_row_index('idx')

# 原表添加索引后左连接,再移除索引列
result = df.with_row_index('idx').join(filtered_df, on='idx', how='left').drop('idx')
print(result)

方法二:直接操作Series替换指定位置

先创建与原表长度一致的空Series,再替换符合条件的位置的值:

import polars as pl

df = pl.DataFrame({
    'cond1': [-1, 0, 1, 2, 2, 3, 4, 5],
    'cond2': ['No', 'No', 'No', 'Yes','Yes', 'Yes', 'Yes', 'Yes']
})

list_new = [1,2,3,4,5]
cond = (pl.col('cond1') >= 1) & (pl.col('cond2') == 'Yes')

# 创建全为None的空Series,类型与列表匹配
output_series = pl.Series([None]*len(df), dtype=pl.Int64)
# 获取符合条件的行索引
target_indices = df.select(pl.int_range(0, pl.count()).filter(cond)).to_series().to_list()
# 替换指定索引位置的值
output_series = output_series.set(target_indices, list_new)

# 添加新列到原表
result = df.with_columns(output_series.alias('output'))
print(result)

两种方法执行后都会得到与Pandas示例一致的结果:

shape: (8, 3)
┌───────┬───────┬────────┐
│ cond1 ┆ cond2 ┆ output │
│ ---   ┆ ---   ┆ ---    │
│ i64   ┆ str   ┆ i64    │
╞═══════╪═══════╪════════╡
│ -1    ┆ No    ┆ null   │
│ 0     ┆ No    ┆ null   │
│ 1     ┆ No    ┆ null   │
│ 2     ┆ Yes   ┆ 1      │
│ 2     ┆ Yes   ┆ 2      │
│ 3     ┆ Yes   ┆ 3      │
│ 4     ┆ Yes   ┆ 4      │
│ 5     ┆ Yes   ┆ 5      │
└───────┴───────┴────────┘

原代码失败原因

你之前尝试的pl.when(conditions).then(list_new)无法工作,是因为Polars的then方法要求传入列表达式(比如pl.col()、pl.Series()等),而不是直接传入Python列表。直接传列表会导致Polars把整个列表作为单一值,赋值给所有符合条件的行,而非逐行分配列表中的元素,因此达不到预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:35:56