更新:已经超过24小时了,代码仍然是仍然尚未完成:)
下面是python代码。基本上,这段代码目前只使用数据集的1%(这就是为什么它被称为sample)。它有32968行只是名字。我把标点符号都改成小写了。在
我的问题是,到目前为止,这段代码已经运行了8个小时,还没有完成。因为,如前所述,我只使用了1%的数据,我需要稍后在整个数据集中再次运行此代码,这将花费100倍的时间。我不认为等800小时是个好主意。所以对于我的问题:
有什么方法可以让它更快吗?是否应该学习spark或mapreduce并尝试将其用于此代码?
编辑:好的,我将尝试添加更多关于代码实际执行的信息。清理前的名称示例:
import pandas as pd
import numpy as np
data = {'clean_name': ['Abbott Laboratories','Apple Computers', 'Apple, Inc.', 'Abercrombie & Fitch Co.', 'ABM Industries Incorporated', 'Ace Hardware Corporation'], 'name_group': np.zeros(6, dtype=int)}
sample = pd.DataFrame(data)
sample
Out[2]:
clean_name name_group
0 Abbott Laboratories 0
1 Apple Computers 0
2 Apple, Inc. 0
3 Abercrombie & Fitch Co. 0
4 ABM Industries Incorporated 0
5 Ace Hardware Corporation 0
然后,我清除了标点符号,并将其全部改为小写。基本上,我想把每个名字和下一个名字进行比较,如果相似,我会给它相同的组号。像这样:
^{pr2}$下面的代码是我想出的:
i = 1
for alpha,beta in itertools.combinations(sample.clean_name, 2):
score = fuzz.token_sort_ratio(alpha, beta)
A = sample.loc[sample.clean_name==alpha, 'name_group'].values[0]
B = sample.loc[sample.clean_name==beta, 'name_group'].values[0]
if score > 60:
if ((B != 0) & (A !=0)): continue
if ((A == 0) & (B !=0)): A = B
elif ((B == 0) & (A !=0)): B = A
elif ((B == 0) & (A ==0)):
A, B = i, i
i += 1
sample.loc[sample.clean_name==alpha, 'name_group'] = A
sample.loc[sample.clean_name==beta, 'name_group'] = B
将
itertools.combinations
用于32k行肯定会使代码变慢。以下是一种在较小的数据集上使用numpy而不是pandas的方法来实现以下目标:利用这篇文章从不同的角度来解决你的问题。在
给定
在这里,我们建立一个小的公司名称列表}:
A
,B
,C
和{编码
第1步
首先,我们将创建一个二维数组,其中水平和垂直索引是相同的公司名称。矩阵中包含合并后的公司名称:
^{pr2}$演示
第2步
其次,我们实现了一个
group
函数来列举类似的公司。给定一个2D数组,一个helper函数(func
)将用于将每个元素“转换”为一个组号:演示
每个公司名称都有一个唯一的编号。在
第3步
现在可以通过切片
groups
数组来访问两个公司的组号:详细信息
第1步
为什么使用数组?numpy数组允许像熊猫一样快速查找。此外,我们可以稍后使用在C级别实现的操作来优化性能(这些操作很快)。在
为什么在数组中合并公司名称?合并字符串的二维数组用于比较公司名称。这种比较方式类似于统计correlation matrix。在
第2步
如何确定组?公司名称被传递到一个特殊的字典(
dd
),该字典只在找到新密钥时分配递增整数。当transform
助手函数应用于每个元素时,此字典用于跟踪组。在为什么要使用helper函数?函数
tranform
将数组中的每个项转换为一个组号。请注意,跟踪字典(lookup
)是用谓词传入的。以下是关于这些group
参数的一些注释:pred=None
),则应用一个默认谓词,该谓词天真地比较具有相同名称的字符串(尤其是沿着diagnol)。在您可能希望使用另一个谓词。例如,从默认谓词来看,任何一组降低的字符串都是等价的,}区分开来(分别是组0和组3):
A == Aa == AaAa
(请参见数组的角点被分配给组0)。下面是另一个示例谓词,它将A
与{如何优化性能?有些操作是vectorized来帮助使用C实现加快代码的速度。在
group
函数中,numpy.frompyfun
包装了helper函数。已经确定这个特殊的"universal function"比向量化函数numpy.vectorize
快。有关优化numpy代码的更多方法,请参见Scipy Lecture Notes。在第3步
如何找到两个公司的组号?这只需从
group
函数中切片返回的数组即可。group_number
是用于查询数组的切片函数。由于第2步中的索引现在是数字的,因此我们从起始的有序序列companies
构建一个反向字典,以按公司名称查找相应的数字索引。注意,反向字典是在切片函数之外构建的,以避免在每次查询后重新构建字典。在性能
有多快是吗?对于10行的简单序列,速度为亚毫秒:
为了演示,让我们将数据放大到1000行左右(除此之外,创建数据集也需要很长时间并消耗内存)。在
只计算矩阵的一半,从而节省一些计算时间:
注意:没有对32k行的数据集执行分析。在
结论
在这种方法中,上述目标是通过以下方式实现的:
考虑在C级优化比较函数的numpy。虽然本文中的性能测试可能仍需要时间,但numpy为进一步优化提供了空间。此外,这段代码很可能在OP的数据集上花费的时间少于8小时。需要进一步的分析来评估这种方法的复杂性。如果复杂性是合理的,用户可以决定如何继续,例如在多个线程上parallel processing。这些任务交给感兴趣的人去做。在
参考文献
相关问题 更多 >
编程相关推荐