除了一种情况外,我很享受 Polars 比 Pandas 的显着加速。我是 Polars 的新手,所以这可能只是我的错误用法。无论如何,这是一个玩具示例: 在单列上,我需要在我的情况下应用自定义函数,它是来自
parse
库(https://github.com/datamade/probablepeople)的
probablepeople
,但问题是通用的。
Plain pandas
apply
与 Polars 具有相似的运行时间,但带有来自 (https://github.com/nalepae/pandaallel) 的
parallel_apply
的 pandas 获得的加速与核心数量成正比。
我觉得Polars只使用单核来实现自定义功能,还是我错过了什么?
如果我正确使用Polars,也许有可能为Polars创建像
pandaralell
这样的工具?
!pip install probablepeople
!pip install pandarallel
import pandas as pd
import probablepeople as pp
import polars as pl
from pandarallel import pandarallel
AMOUNT = 1_000_000
#Pandas:
df = pd.DataFrame({'a': ["Mr. Joe Smith"]})
df = df.loc[df.index.repeat(AMOUNT)].reset_index(drop=True)
df['b'] = df['a'].apply(pp.parse)
#Pandarallel:
pandarallel.initialize(progress_bar=True)
df['b_multi'] = df['a'].parallel_apply(pp.parse)
#Polars:
dfp = pl.DataFrame({'a': ["Mr. Joe Smith"]})
dfp = dfp.select(pl.all().repeat_by(AMOUNT).explode())
dfp = dfp.with_columns(pl.col('a').map_elements(pp.parse).alias('b'))
pandarallel
使用多重处理。
您还可以 使用带有极坐标的多重处理。
我们使用 multiprocessing.pool.Pool.imap 和默认设置作为示例。
import multiprocessing
import polars as pl
import probablepeople as pp
from pip._vendor.rich.progress import track
def parallel_apply(function, column):
with multiprocessing.get_context("spawn").Pool() as pool:
return pl.Series(pool.imap(function, track(column)))
if __name__ == "__main__":
df = pl.DataFrame({
"name": ["Mr. Joe Smith", "Mrs. I & II Alice Random"]
})
df = df.with_columns(pp =
pl.col("name").map_batches(lambda col: parallel_apply(pp.parse, col))
)
print(df)
.map_batches()
用于将整列传递给函数。
该列与要在池中执行的 Python 函数一起传递给
parallel_apply
,例如pp.parse
rich.progress.track()
(也与 pip
捆绑在一起)用于进度条。
Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
shape: (2, 2)
┌──────────────────────────┬───────────────────────────────────┐
│ name ┆ pp │
│ --- ┆ --- │
│ str ┆ list[list[str]] │
╞══════════════════════════╪═══════════════════════════════════╡
│ Mr. Joe Smith ┆ [["Mr.", "PrefixMarital"], ["Joe… │
│ Mrs. I & II Alice Random ┆ [["Mrs.", "PrefixMarital"], ["I"… │
└──────────────────────────┴───────────────────────────────────┘
作为基本比较,创建一个
1_000_000
行数据框 - 我得到以下运行时间:
多处理 | 持续时间 |
---|---|
是的 | 1分23秒 |
不 | 5平方米 |