摘要:我正在寻找一堆数据之间的拼写错误,而且它正在永远消失
我正在迭代几个CSV文件(总计数百万行?),每一个我都在迭代一个json子值,它可能有200个字符串要搜索。对于每个循环或json值,我向每个数据帧添加一列,然后使用lambdas函数使用Levenshtein的搜索算法来查找拼写错误。然后我输出包含潜在拼写错误的任何行的结果 代码:
for file in file_list: #20+ files
df = pd.read_csv(file, usecols=["search column","a bunch of other columns...") #50k lines each-ish
for v in json_data.values(): #30 ish json values
for row in v["json_search_string"]: #200 ish substrings
df_temp = df
df_temp['jelly'] = row
df_temp['difference'] = df_temp.apply(lambda x: jellyfish.levenshtein_distance(x['search column'],x['jelly']), axis=1)
df_agg = df_temp[df_temp['difference'] <3]
if os.path.isfile(filepath+"levenshtein.csv"):
with open(filepath+"levenshtein.csv", 'a') as f:
df_agg.to_csv(f, header=False)
else:
df_agg.to_csv(filtered_filepath+"levenshtein.csv")
之前我尝试过相同的算法,但只是为了保持简短,而不是通过每个CSV的所有JSON值进行迭代,我只是做了一个这样的JSON值:
for file in file_list: #20+ files
df = pd.read_csv(file, usecols=["search column","a bunch of other columns...") #50k lines each-ish
for row in data['z']['json_search_string']:
#levenshtein algorithm above
以上循环需要 100分钟才能完成! (编辑:每次运行lambda函数大约需要1-3秒)并且JSON文件中大约有30个。关于如何压缩算法并使其更快的任何想法?我想也许我可以把所有200个json子字符串并将它们作为列添加到每个df中,并以某种方式运行一个lambda函数,一次搜索所有列,但我不知道该怎么做。这样我每次只会迭代20个文件30次,而不是第三层for循环添加的数千次迭代。想法?
注意: 以下是数据可能的示例: JSON数据
{
"A": {
"email": "blah",
"name": "Joe Blah",
"json_search_string": [
"Company A",
"Some random company name",
"Company B",
"etc",
"..."
和csv列:
ID, Search Column, Other Columns
1, Clompany A, XYZ
2, Company A, XYZ
3, Some misspelled company, XYZ
etc
答案 0 :(得分:0)
嗯,很难回答性能提升问题。 根据努力和表现,这里有一些建议。
通过重新安排代码逻辑进行小幅调整。努力:小。预期增强:小。通过查看代码,我知道您要将File
(数字20)中的单词与固定JSON File
(仅一个)进行比较。为什么不首先从JSON File
准备固定单词列表,并将其用于以下所有比较,而不是为每个File
阅读JSON File
?逻辑如下:
# prepare fixed words from JSON DATA
fixed_words = []
for v in json_data.values():
fixed_words += v["json_search_string"]
# looping over each file, and compare them with word from fixed words
for f in file_list:
# do the comparison and save.
使用多处理。努力:小。预期增强:中位数。由于您的所有工作都相似,为什么不尝试多处理?您可以对每个文件应用多处理或在执行dataframe.apply
时应用多处理。多处理有很多来源,请看一下。您的案例很容易实现。
使用其他语言实现Levenshtein距离。代码的瓶颈是Levenshtein距离的计算。你使用了水母python包,这是一个纯粹的python(当然,性能对于大型集合来说并不好)。以下是其他一些选择:
一个。已经存在具有C / C ++实现的python包。努力:小。预期增强:高。感谢@Corley Brigman的评论,editdistance是您可以使用的一个选项。
湾Cyphon自我实现。努力:中位数。增强:中位数或高位。检查pandas文档Performance
℃。由C / C ++自我实现作为包装器。努力:高;预期增强:高。查看Wrapping with C/C++
您可以使用我的一些建议来获得更高的性能。 希望这会有所帮助。
答案 1 :(得分:0)
您可以将代码更改为:
for file in file_list: #20+ files
df = pd.read_csv(file, usecols=["search column","a bunch of other columns...") #50k lines each-ish
x_search = x['search column']
for v in json_data.values(): #30 ish json values
for row in v["json_search_string"]: #200 ish substrings
mask = [jellyfish.levenshtein_distance(s1,s2) < 3 for s1,s2 in zip(x_search, row) ]
df_agg = df_temp[mask]
if os.path.isfile(filepath+"levenshtein.csv"):
with open(filepath+"levenshtein.csv", 'a') as f:
df_agg.to_csv(f, header=False)
else:
df_agg.to_csv(filtered_filepath+"levenshtein.csv")
apply会返回一份可能更贵的系列副本:
a = range(10**4)
b = range(10**4,2*(10**4))
%timeit [ (x*y) <3 for x,y in zip(a,b)]
%timeit pd.DataFrame([a,b]).apply(lambda x: x[0]*x[1] < 3 )
1000次循环,最佳3次:每次循环1.23 ms
1个循环,最佳3:668 ms每个循环