为什么这个apply()自定义函数在Polars中比在Pandas中慢

eufgjt7s  于 2023-01-11  发布在  其他
关注(0)|答案(1)|浏览(350)

我在Jupyter笔记本上运行了以下代码,但对类似的Pandas代码更快感到失望。希望有人能在Polars中展示更聪明的方法。
极地版本

def cleanse_text(sentence):
    RIGHT_QUOTE = r"(\u2019)"
    sentence = re.sub(RIGHT_QUOTE, "'", sentence)
    sentence = re.sub(r" +", " ", sentence)
    return sentence.strip()
df = df.with_columns(pl.col("text").apply(lambda x: cleanse_text(x)).keep_name())

Pandas版

def cleanse_text(sentence):
    RIGHT_QUOTE = r"(\u2019)"
    sentence = re.sub(RIGHT_QUOTE, "'", sentence)    
    sentence = re.sub(r" +", " ", sentence)
    return sentence.strip() 
df["text"] = df["text"].apply(lambda x: cleanse_text(x))

当我在一个有750,000行文本的 Dataframe 上运行这个程序时,上面的Pandas版本比Polars版本快10%。

ggazkfy8

ggazkfy81#

在这种情况下,您可以将Series.applyre.sub合并,而不是将Series.str.replace的2个示例链接起来,最后添加Series.str.strip。这样通常会更快(请参阅答案末尾的原因),但对于polars尤其如此。

Pandas版

import pandas as pd
t = "'Hello  World\u2019 "
df = pd.DataFrame({'text': [t]*750000})

df['text'] = (df['text']
              .str.replace('\u2019',"'", regex=True)
              .str.replace(' +',' ', regex=True)
              .str.strip())

df.head()

            text
0  'Hello World'
1  'Hello World'
2  'Hello World'
3  'Hello World'
4  'Hello World'

极地版本

import polars as pl
t = "'Hello  World\u2019 "
df_pl = pl.DataFrame({'text': [t]*750000})

df_pl = (df_pl
         .with_column(pl.col('text')
                      .str.replace('\u2019',"'")
                      .str.replace(' +',' ')
                      .str.strip()))

df_pl.head()

┌───────────────┐
│ text          │
│ ---           │
│ str           │
╞═══════════════╡
│ 'Hello World' │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 'Hello World' │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 'Hello World' │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 'Hello World' │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 'Hello World' │
└───────────────┘

性能比较

每种方法的timeit检测结果(检查dfs是否相等):

method  timeit (s)      perc
0  pandas_new    1.092429  1.000000
1  pandas_old    1.553892  1.422419
2  polars_new    0.151107  0.138322
3  polars_old    1.851840  1.695158

如您所见,pandaspolars的两种新方法都比原始方法快,polars方法明显赢家,仅占新pandas方法的13.8%。
那么,为什么Series.str.replace(或:str.strip)比Series.apply快得多?原因是前者一次对整个Series(例如“列”)执行一个运算符(“向量化”),而后者分别为Series中的每个元素调用Python函数。例如lambda x: cleanse_text(x)表示:将UDF(用户定义函数)应用于列中的第一个元素,列中的第二个元素,等等。在较大的集合中,这将产生巨大的差异。也可参考documentationpl.DataFrame.apply

相关问题