pandas df.apply 函数对 DataFrame 非常慢

pandas df.apply function to dataframe is incredibly slow

提问人:Gogo 提问时间:10/23/2023 最后编辑:mozwayGogo 更新时间:10/24/2023 访问量:88

问:

我想从数据帧列中删除非英语单词,但以下函数已经运行了很长时间而没有打印结果。

我可以在我的函数中实现任何内容,以便我的代码的最后一行 include 将产生快速结果?df.apply

请记住,我在这里使用的比我需要帮助的要小得多,后者包含 7000 多行。dataframe

import pandas as pd
import numpy as np
from nltk.corpus import brown

df = pd.DataFrame()
df['text'] = ['the fulton 5ddef', 'aerderdrdfg country grand', 'jury sdcvwefdf said']
df['length'] = [3,3,3]
def remove_words(words):  
    english_words = list(set(w.lower() for w in brown.words())) # approx 50000 words
    split=words.split()
    english_words_in_sentence = np.intersect1d(english_words, split)
    return english_words_in_sentence

# never stops running when applied to a larger dataframe
df['text_clean'] = df['text'].apply(lambda x: remove_words(x))

df.head()

通过使用我尽可能多地矢量化函数,因为 for 循环需要更长的时间,但计时仍然是一个大问题numpyremove_words

Python pandas 字符串 数据帧 性能

评论

1赞 Serge Ballesta 10/23/2023
numpy代表数字 Python。它在处理数字时提供了非常好的性能。但是一旦你使用了 Python 对象,它就必须在常规 Python 环境和 numpy 环境之间不断切换。所以:通过使用 numpy,我矢量化了 remove_words 函数 - 不,你没有,因为你使用 Python 对象而不是 numpy 特定类型。最好在这里使用普通的 Python,并且与在列表或 numpy 数组中搜索相比,在集合中搜索的性能会更好。

答:

1赞 mozway 10/23/2023 #1

您正在重建数据集中每一行的英语单词列表,只需执行此操作一次并在其上构建函数,同时保留 为了进行有效的隶属度测试:set

english_words = set(w.lower() for w in brown.words())

def remove_words(text, word_list=english_words):  
    return [w for w in text.split() if w in word_list]

df['text_clean']=df['text'].apply(lambda x: remove_words(x))

您甚至不需要:apply

english_words = set(w.lower() for w in brown.words())

df['text_clean'] = [[w for w in s.split() if w in english_words]
                    for s in df['text']]

输出:

                        text  length        text_clean
0           the fulton 5ddef       3     [the, fulton]
1  aerderdrdfg country grand       3  [country, grand]
2        jury sdcvwefdf said       3      [jury, said]
0赞 snqy 10/24/2023 #2

您可能想尝试以下操作:

import numpy as np
import pandas as pd

df = pd.DataFrame()
df["text"] = [
    "The fulton 5ddef",
    "aerderdrdfg country grand asddf lmao",
    "jury sdcvwefdf said fulton asdf",
]
df["length"] = df["text"].str.split().str.len()
english_words = np.array(list(set(w.lower() for w in brown.words())))

# get df["text"] as list of arrays
split_arr = df["text"].str.lower().str.split().to_numpy()
# flatten list of arrays
long = np.concatenate(split_arr).ravel()
# get intersection array
intersections = np.isin(long, english_words)

# filter only valid words
filtered_words = long[intersections]
# compute groups
indices = np.cumsum(df["length"])[:-1]
# split intersections according to indices
mask = np.split(intersections, indices)
# compute short indices (excluding filtered out words)
short_indices = np.cumsum([np.sum(l) for l in mask])[:-1]
# insert in df
df["text_clean"] = np.split(filtered_words, short_indices)
print(df)

                                   text  length              text_clean
0                      The fulton 5ddef       3           [the, fulton]
1  aerderdrdfg country grand asddf lmao       5  [country, grand, lmao]
2       jury sdcvwefdf said fulton asdf       5    [jury, said, fulton]

首先,我们将 df[“text”] 列转换为一个 numpy 数组并展平它。 我们过滤掉只在长数组中而不在english_words中的单词。

我们计算每一行的组,然后将这些组应用于交集数组,我们使用交集数组数组计算新组。我们在过滤后的单词中使用这个新分组,并将其放在 df 中。