python - Polars - 用其他列的值替换列中的部分字符串

标签 python string replace python-polars

所以我有一个看起来像这样的 Polars 数据框

df = pl.DataFrame(
    {
        "ItemId": [15148, 15148, 24957],
        "SuffixFactor": [19200, 200, 24],
        "ItemRand": [254, -1, -44],
        "Stat0": ['+5 Defense', '+$i Might', '+9 Vitality'],
        "Amount": ['', '7', '']
    }
)

每当 Stat0 包含 i$ 时,我想用 Amount 替换“Stat0”列中的 $i

我尝试了一些不同的事情,例如:

df = df.with_column(
    pl.col('Stat0').str.replace(r'\$i', pl.col('Amount'))
)

预期结果

result = pl.DataFrame(
    {
        "ItemId": [15148, 15148, 24957],
        "SuffixFactor": [19200, 200, 24],
        "ItemRand": [254, -1, -44],
        "Stat0": ['+5 Defense', '+7 Might', '+9 Vitality'],
        "Amount": ['', '7', '']
    }
)

但这似乎行不通。

我希望有人能提供帮助。

最好的问候

最佳答案

编辑:Polars >= 0.14.4

从 Polars 0.14.4 开始,replacereplace_all 表达式允许 value 参数的表达式。因此,我们可以更简单地解决这个问题:

df.with_column(
    pl.col('Stat0').str.replace(r'\$i', pl.col('Amount'))
)
shape: (3, 5)
┌────────┬──────────────┬──────────┬─────────────┬────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ Stat0       ┆ Amount │
│ ---    ┆ ---          ┆ ---      ┆ ---         ┆ ---    │
│ i64    ┆ i64          ┆ i64      ┆ str         ┆ str    │
╞════════╪══════════════╪══════════╪═════════════╪════════╡
│ 15148  ┆ 19200        ┆ 254      ┆ +5 Defense  ┆        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ +7 Might    ┆ 7      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆ +9 Vitality ┆        │
└────────┴──────────────┴──────────┴─────────────┴────────┘

极地 < 0.14.4

问题是 replace 方法不接受表达式,只接受常量。因此,我们不能使用列作为替换值,只能使用常量。

我们可以通过两种方式解决这个问题。

慢:使用apply

此方法使用 python 代码执行替换。由于我们正在使用 apply 执行 python 字节码,因此它会很慢。如果您的 DataFrame 很小,那么这不会太慢。

(
    df
    .with_column(
        pl.struct(['Stat0', 'Amount'])
        .apply(lambda cols: cols['Stat0'].replace('$i', cols['Amount']))
        .alias('Stat0')
    )
)
shape: (3, 5)
┌────────┬──────────────┬──────────┬─────────────┬────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ Stat0       ┆ Amount │
│ ---    ┆ ---          ┆ ---      ┆ ---         ┆ ---    │
│ i64    ┆ i64          ┆ i64      ┆ str         ┆ str    │
╞════════╪══════════════╪══════════╪═════════════╪════════╡
│ 15148  ┆ 19200        ┆ 254      ┆ +5 Defense  ┆        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ +7 Might    ┆ 7      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆ +9 Vitality ┆        │
└────────┴──────────────┴──────────┴─────────────┴────────┘

快速:使用split_exactwhen/then/otherwise

此方法使用所有 Polars 表达式。因此,它会快得多,尤其是对于大型 DataFrame。

(
    df
    .with_column(
        pl.col('Stat0').str.split_exact('$i', 1)
    )
    .unnest('Stat0')
    .with_column(
        pl.when(pl.col('field_1').is_null())
        .then(pl.col('field_0'))
        .otherwise(pl.concat_str(['field_0', 'Amount', 'field_1']))
        .alias('Stat0')
    )
    .drop(['field_0', 'field_1'])
)
shape: (3, 5)
┌────────┬──────────────┬──────────┬────────┬─────────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ Amount ┆ Stat0       │
│ ---    ┆ ---          ┆ ---      ┆ ---    ┆ ---         │
│ i64    ┆ i64          ┆ i64      ┆ str    ┆ str         │
╞════════╪══════════════╪══════════╪════════╪═════════════╡
│ 15148  ┆ 19200        ┆ 254      ┆        ┆ +5 Defense  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ 7      ┆ +7 Might    │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆        ┆ +9 Vitality │
└────────┴──────────────┴──────────┴────────┴─────────────┘

工作原理:我们首先使用 split_exact 拆分 $i 上的 Stat0 列.这将产生一个结构。

(
    df
    .with_column(
        pl.col('Stat0').str.split_exact('$i', 1)
    )
)
shape: (3, 5)
┌────────┬──────────────┬──────────┬──────────────────────┬────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ Stat0                ┆ Amount │
│ ---    ┆ ---          ┆ ---      ┆ ---                  ┆ ---    │
│ i64    ┆ i64          ┆ i64      ┆ struct[2]            ┆ str    │
╞════════╪══════════════╪══════════╪══════════════════════╪════════╡
│ 15148  ┆ 19200        ┆ 254      ┆ {"+5 Defense",null}  ┆        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ {"+"," Might"}       ┆ 7      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆ {"+9 Vitality",null} ┆        │
└────────┴──────────────┴──────────┴──────────────────────┴────────┘

请注意,当 Stat0 不包含 $i 时,结构的第二个成员为 null。我们将利用这一事实来发挥我们的优势。

在下一步中,我们使用 unnest 将结构分解为单独的列.

(
    df
    .with_column(
        pl.col('Stat0').str.split_exact('$i', 1)
    )
    .unnest('Stat0')
)
shape: (3, 6)
┌────────┬──────────────┬──────────┬─────────────┬─────────┬────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ field_0     ┆ field_1 ┆ Amount │
│ ---    ┆ ---          ┆ ---      ┆ ---         ┆ ---     ┆ ---    │
│ i64    ┆ i64          ┆ i64      ┆ str         ┆ str     ┆ str    │
╞════════╪══════════════╪══════════╪═════════════╪═════════╪════════╡
│ 15148  ┆ 19200        ┆ 254      ┆ +5 Defense  ┆ null    ┆        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ +           ┆  Might  ┆ 7      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆ +9 Vitality ┆ null    ┆        │
└────────┴──────────────┴──────────┴─────────────┴─────────┴────────┘

这将创建两个新列:field_0field_1

从这里开始,我们使用 when/then/otherwiseconcat_str构建最终结果

基本上:

  • $i没有出现在Stat0列时,则字符串不拆分,field_1null,因此我们可以按原样使用 field_0 中的值。
  • $i 确实出现在 Stat0 中时,字符串会被分成两部分:field_0field_1。我们只需将各部分重新连接在一起,将 Amount 放在中间。
(
    df
    .with_column(
        pl.col('Stat0').str.split_exact('$i', 1)
    )
    .unnest('Stat0')
    .with_column(
        pl.when(pl.col('field_1').is_null())
        .then(pl.col('field_0'))
        .otherwise(pl.concat_str(['field_0', 'Amount', 'field_1']))
        .alias('Stat0')
    )
)
shape: (3, 7)
┌────────┬──────────────┬──────────┬─────────────┬─────────┬────────┬─────────────┐
│ ItemId ┆ SuffixFactor ┆ ItemRand ┆ field_0     ┆ field_1 ┆ Amount ┆ Stat0       │
│ ---    ┆ ---          ┆ ---      ┆ ---         ┆ ---     ┆ ---    ┆ ---         │
│ i64    ┆ i64          ┆ i64      ┆ str         ┆ str     ┆ str    ┆ str         │
╞════════╪══════════════╪══════════╪═════════════╪═════════╪════════╪═════════════╡
│ 15148  ┆ 19200        ┆ 254      ┆ +5 Defense  ┆ null    ┆        ┆ +5 Defense  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 15148  ┆ 200          ┆ -1       ┆ +           ┆  Might  ┆ 7      ┆ +7 Might    │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 24957  ┆ 24           ┆ -44      ┆ +9 Vitality ┆ null    ┆        ┆ +9 Vitality │
└────────┴──────────────┴──────────┴─────────────┴─────────┴────────┴─────────────┘

关于python - Polars - 用其他列的值替换列中的部分字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73427091/

相关文章:

regex - Perl:从当前位置替换模式直到行尾

python - 无法构建 Go 应用程序 : . .. : can't find import: "code. google.com/p/go.net/html

python - 使用python返回参数到命令行

java - 等式 -e**-((-log(7)/100.0)*(100-x))+7 返回 NaN

python - 如何在 Xcode 中将 Python 函数导入 C?

string - 如何加速替换字符串中某些字符的 'divide and conquer' XSLT 模板?

Jquery 替换 JQuery 中的表行

php - 分别生成64个字符的十六进制字符串

java - 使用 Java 将字符串转换为 XML

javascript - 转义字符串字符而无需手动转义它们