Python Polars - 如何用字典中的值列表替换 df 列中的字符串?

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

这是对之前回答过的问题的后续

有一个像这样的大型数据框 df (在“SKU”列中列出)

| SKU                                                                  | Count | Percent     
|----------------------------------------------------------------------|-------|-------------|
| "('000000009100000749',)"                                            | 110   | 0.029633621 |
| "('000000009100000749', '000000009100000776')"                       | 1     | 0.000269397 |
| "('000000009100000749', '000000009100000776', '000000009100002260')" | 1     | 0.000269397 |
| "('000000009100000749', '000000009100000777', '000000009100002260')" | 1     | 0.000269397 |
| "('000000009100000749', '000000009100000777', '000000009100002530')" | 1     | 0.000269397 |

需要将“SKU”列中的值替换为字典 df_unique 中的相应值,如下所示(请忽略下面的格式,它是一个字典):

skus str 代码i64
000000009100000749 1
000000009100000785 2
000000009100002088 3

我已经尝试过这段代码:

replacements = pl.col("SKU")

for old, new in df_unique.items():
    replacements = replacements.str.replace_all(old, new)
df = df.select(replacements)

出现此错误: SchemaError:数据类型系列:列表(Utf8)!= Utf8

我尝试将列值更改为字符串,尽管我认为这是多余的,但同样的错误

df= df.with_column(
    pl.col('SKU').apply(lambda row: [str(x) for x in row])
    )

关于我做错了什么有什么指导吗?

python python-polars
3个回答
2
投票

如果您显示列的实际列表类型,将会有所帮助:

看起来你有“字符串化”元组,但并不完全清楚。

df = pl.DataFrame({
   "SKU": [["000000009100000749"], ["000000009100000749", "000000009100000776"]]
})

sku_to_code = {
    "000000009100000749": 1,
    "000000009100000785": 2,
    "000000009100002088": 3
}
>>> df
shape: (2, 1)
┌─────────────────────────────────────┐
│ SKU                                 │
│ ---                                 │
│ list[str]                           │
╞═════════════════════════════════════╡
│ ["000000009100000749"]              │
│ ["000000009100000749", "00000000... │
└─────────────────────────────────────┘

.list.eval()
允许您在列表上运行表达式。

pl.element()
可以用来引用
list.eval

里面的列表
replace_sku = pl.element()
for old, new in df_unique.items():
    replace_sku = replace_sku.str.replace_all(old, str(new), literal=True)
df.select(pl.col("SKU").list.eval(replace_sku))
shape: (2, 1)
┌─────────────────────────────┐
│ SKU                         │
│ ---                         │
│ list[str]                   │
╞═════════════════════════════╡
│ ["1"]                       │
│ ["1", "000000009100000776"] │
└─────────────────────────────┘

1
投票

SKU
具有
list[str]
dtype,但接下来您调用用于字符串的属性
.str
(此处:
replacements.str.replace_all(old, new)
)。您应该将属性
.arr
与具有
list
dtype 和 相应方法的列一起使用。

您可以将下面的 sol-n 与

.apply()
一起使用,或者通过 jqurious 使用 sol-n,其工作速度更快(因为
.arr.eval()
允许并行运行所有表达式)

d = {"000000009100000749": 1, "000000009100000776": 2}
df = pl.DataFrame({
    "SKU": [["000000009100000749", "000000009100000776"]]
})
    

df = df.with_column(
    col("SKU").apply(
        lambda row: [d[i] for i in row]
    ).alias("SKU_replaced")
)

1
投票

来自 jquriousglebcom 的两个解决方案都可以完美地解决所提出的问题。

我没有意识到 df_unique 是字典列表而不是字典,因此必须根据情况调整解决方案。这是 jqurious 稍微修改过的解决方案(更改循环以迭代 df_unique 字典列表中的元素):

replace_sku = pl.element()
for item in df_unique:
    old = item['SKU']
    new = item['code']
    replace_sku = replace_sku.str.replace_all(old, str(new), literal=True)

df = df.select(pl.col("SKU").list.eval(replace_sku, parallel=True))
© www.soinside.com 2019 - 2024. All rights reserved.