将 Python 字典映射到 Polars 系列

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

在 Pandas 中,我们可以使用

map
函数将字典映射到系列,以使用映射值创建另一个系列。更一般地说,我相信它调用参数的索引运算符,即
[]

import pandas as pd

dic = { 1: 'a', 2: 'b', 3: 'c' }

pd.Series([1, 2, 3, 4]).map(dic) # returns ["a", "b", "c", NaN]

我还没有找到直接在 Polars 中执行此操作的方法,但找到了一些替代方案。这些是推荐的方法吗?或者有更好的方法吗?

import polars as pl

dic = { 1: 'a', 2: 'b', 3: 'c' }

# Approach 1 - apply
pl.Series([1, 2, 3, 4]).apply(lambda v: dic.get(v, None)) # returns ["a", "b", "c", null]

# Approach 2 - left join
(
    pl.Series([1, 2, 3, 4])
    .alias('key')
    .to_frame()
    .join(
        pl.DataFrame({
            'key': list(dic.keys()),
            'value': list(dic.values()),
        }),
        on='key', how='left',
    )['value']
) # returns ["a", "b", "c", null]

# Approach 3 - to pandas and back
pl.from_pandas(pl.Series([1, 2, 3, 4]).to_pandas().map(dic)) # returns ["a", "b", "c", null]

我看到了这个关于映射表达式字典的答案,但由于它的链

when/then/otherwise
它可能不适用于巨大的字典。

python-polars
5个回答
8
投票

更新2023-03-20

Polars 有专用的

map_dict
表情。用这个。

旧答案

将 python 字典映射到极坐标系上应该始终被视为反模式。这将非常慢,并且您想要的在语义上等于连接。

使用联接。它们经过深度优化、多线程并且不使用 python。

示例

import polars as pl

dic = { 1: 'a', 2: 'b', 3: 'c' }

mapper = pl.DataFrame({
    "keys": list(dic.keys()),
    "values": list(dic.values())
})

pl.Series([1, 2, 3, 4]).to_frame("keys").join(mapper, on="keys", how="left").to_series(1)
Series: 'values' [str]
[
    "a"
    "b"
    "c"
    null
]


6
投票

自版本

0.16.3
以来,Polars具有
Expr.map_dict
方法,自
0.16.7
以来,
Series.map_dict
方法可以使用如下:

import polars as pl

mapping_dict = {1: "a", 2: "b", 3: "c"}

# pl.Series.map_dict
pl.Series([1, 2, 3, 4]).map_dict(mapping_dict)

# pl.Expr.map_dict
pl_df = pl.Series(name="to_map_col", values=[1, 2, 3, 4]).to_frame()

pl_df.with_columns(pl.col("to_map_col").map_dict(mapping_dict))

1
投票

Polars 有专用方法

replace
:

import polars as pl

dic = { 1: 'a', 2: 'b', 3: 'c' }
pl.Series([1, 2, 3, 4]).replace(dic)  # returns [a, b, c, 4]

参见手册: https://docs.pola.rs/py-polars/html/reference/series/api/polars.Series.replace.html#polars-series-replace


0
投票

Polars 有

pl.Series.replace
用于系列,
pl.Expr.replace
用于数据帧。

注意。 确保在处理映射未涵盖的值时传递

default=None
以获得与 pandas 相同的行为(替换为
None
而不是保留原始值)。

import polars as pl

mapping = {
    "a": 1,
    "b": 2,
    "c": 3,
}

pl.Series(["a", "b", "c", "d"]).replace(mapping, default=None)
shape: (4,)
Series: '' [i64]
[
    1
    2
    3
    null
]

-1
投票

Polars 是一个很棒的工具,但即使是很棒的工具也并不适用于所有情况,这就是其中之一。使用简单的 Python 列表理解会更快。

你可以这样做:

[dic[x] if x in dic.keys() else None for x in [1,2,3,4]]

在我的电脑上,使用

%%timeit
的时间是800ns

对比

pl.Series([1, 2, 3, 4]).to_frame("keys").join(pl.DataFrame([{'keys':x, 'values':y} for x,y in dic.items()]), on="keys", how="left").to_series(1)

需要 434μs。

请注意,第一个以纳秒为单位,而第二个以微秒为单位,因此实际上是 800ns 与 434000ns。

© www.soinside.com 2019 - 2024. All rights reserved.