Polars - 如何用 Polars 表达式替换 df 中特定行和列的值(例如 df[3,4]=12)?

问题描述 投票:0回答:2

我知道 Polars 表达式是按列并行化的,用于读取、计算以及输入/更改 DataFrame 中的数据。 所以,速度非常快...

但是,我找不到将行和列的特定值更改为df[1,'a']=12

Polars Expression
我该怎么办?

以下是我想要的方法。

import polars as pl
df = pl.DataFrame(
    {
        "a": [1,2,3,4,5,6,7,8],
        "b": [8,9,0,1,2,3,4,5],
        "c": [0,0,0,0,0,0,0,0],
        "d": [0,0,0,0,0,0,0,0],
    }
)
df = df.with_columns(pl.all().cast(pl.Float64))

df[7,'c']=12   
df[7,'d']=15
# I want this to below way that Polars Expressions
# => df.select(?)(
        pl.col('c').row(7) = 12
        pl.col('d').row(7) = 15
     )

print(df)
shape: (8, 4)
┌─────┬─────┬──────┬──────┐
│ a   ┆ b   ┆ c    ┆ d    │
│ --- ┆ --- ┆ ---  ┆ ---  │
│ f64 ┆ f64 ┆ f64  ┆ f64  │
╞═════╪═════╪══════╪══════╡
│ 1.0 ┆ 8.0 ┆ 0.0  ┆ 0.0  │
│ 2.0 ┆ 9.0 ┆ 0.0  ┆ 0.0  │
│ 3.0 ┆ 0.0 ┆ 0.0  ┆ 0.0  │
│ 4.0 ┆ 1.0 ┆ 0.0  ┆ 0.0  │
│ 5.0 ┆ 2.0 ┆ 0.0  ┆ 0.0  │
│ 6.0 ┆ 3.0 ┆ 0.0  ┆ 0.0  │
│ 7.0 ┆ 4.0 ┆ 0.0  ┆ 0.0  │
│ 8.0 ┆ 5.0 ┆ 12.0 ┆ 15.0 │
└─────┴─────┴──────┴──────┘
python indexing row expression python-polars
2个回答
2
投票

极性数据帧是不可变的,这意味着您无法像 pandas 那样更新单个单元格值。你必须立即更换整个东西。后端内存足够智能,不需要复制它,但语法就是这样。

jquirous 尚未涵盖的一种方法是:

df = (
    df.with_row_count('i') 
        .select(
        pl.exclude('c','d'), 
        structcol=pl.when(pl.col('i')==7) 
            .then(pl.struct(c=12, d=15)) 
            .otherwise(pl.struct(c=pl.col('c'), d=pl.col('d'))))
        .unnest('structcol')
        .drop('i')
        )

本质上,您使用

with_row_count
创建一个表示行索引的列,然后,由于您想要更改两列,因此您使用一个结构来保存这两个值,稍后您将
unnest
。为了使
unnest
正常工作,您必须排除
c
d
列,否则
unnest
将因名称冲突而出错。最后,删除
i
列,以便最终得到与开始时相同的形状。

另一件可行但反模式的事情是将 df 切片,然后再次将其连接在一起

row_to_change=7
df=pl.concat([
    df[0:row_to_change], 
    df[row_to_change].with_columns(c=12.0,d=15.0),
    df[row_to_change+1:]])

顺便说一句,我建议无论您做什么来推断第 7 行是您想要更改的行,都将其合并到更改中,而不是根据行索引进行更改。换句话说,在此之前您已经有一个步骤告诉您第 7 行是要更改的行,现在是更改第 7 行的步骤。您应该将此步骤与该步骤合并并同时执行这两个步骤。


1
投票

df[...] = 
执行
.set_at_idx()
- 那里的文档显示了如何使用
.when

pl.when(pl.col("row_nr") == 1).then(10).otherwise(pl.col("a")).alias("a")

设置多个值将涉及每个值的表达式:

pl.when(pl.col("row_nr") == 1).then(10).otherwise(pl.col("a")).alias("a"),
pl.when(pl.col("row_nr") == 2).then(20).otherwise(pl.col("b")).alias("b")

以下是我见过的一些替代方法:

  1. .map
    内使用
    .then
df.with_row_count().with_columns(
   pl.when(pl.col("row_nr") == 7)
     .then(pl.col("c", "d").map(lambda col: dict(c=12, d=15).get(col.name)))
     .otherwise(pl.col("c", "d"))
).drop("row_nr")
  1. 多个
    .when/.then
df.with_row_count().with_columns(
   pl.when(pl.col("row_nr") == row_nr)
     .then(pl.lit(value).alias(col))
     .otherwise(pl.col(col))
   for row_nr, col, value in [
      (7, "c", 12),
      (7, "d", 15)
   ]
).drop("row_nr")
  1. 创建一个数据框并
    .update
changes = [dict(row_nr=7, c=12, d=15)]

(df.with_row_count() 
   .with_columns(pl.col("row_nr").cast(pl.Int64))
   .update(
      pl.DataFrame(changes), 
      on="row_nr")
   .drop("row_nr"))
  1. .update
    .map_dict
df.update(
   df.with_row_count()
     .select(pl.col("row_nr").map_dict({7: dict(c=12, d=15)}))
     .unnest("row_nr")
)
© www.soinside.com 2019 - 2024. All rights reserved.