提问人:Gogo 提问时间:10/23/2023 最后编辑:mozwayGogo 更新时间:10/24/2023 访问量:88
pandas df.apply 函数对 DataFrame 非常慢
pandas df.apply function to dataframe is incredibly slow
问:
我想从数据帧列中删除非英语单词,但以下函数已经运行了很长时间而没有打印结果。
我可以在我的函数中实现任何内容,以便我的代码的最后一行 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 循环需要更长的时间,但计时仍然是一个大问题numpy
remove_words
答:
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 中。
下一个:循环访问列表中的字符串值
评论
numpy
代表数字 Python。它在处理数字时提供了非常好的性能。但是一旦你使用了 Python 对象,它就必须在常规 Python 环境和 numpy 环境之间不断切换。所以:通过使用 numpy,我矢量化了 remove_words 函数 - 不,你没有,因为你使用 Python 对象而不是 numpy 特定类型。最好在这里使用普通的 Python,并且与在列表或 numpy 数组中搜索相比,在集合中搜索的性能会更好。