【发布时间】:2016-01-01 20:30:31
【问题描述】:
我在不止一个意义上是新来的。在我第一次尝试熟悉任何编程语言时,关于我的第一个脚本的第一篇文章。鉴于此,您可能会发现这个项目过于雄心勃勃,但是,嘿,边做边学一直是要走的路。我正在尽我所能在这里满足stackoverflow-etiquette,但如果我违反了任何规定,请告诉我。
我想编写一段代码,它可以应用某种模糊逻辑来匹配非结构化公司名称表(例如 Google)与结构化公司名称表(例如 Google Inc.)和丹麦公司标识符(@ 987654323@)。
我可以通过谷歌搜索找到一些代码,并且我设法操纵它们来处理我的项目。我发现 stringdist 包中包含的 Jaro-Winkler 算法特别适用于公司名称。当尝试将 40 个非结构化公司名称与数百个结构化名称进行比较和匹配时,该脚本工作得非常好,但我需要将大约 4000 个非结构化名称与包含 700k 个结构化名称的表进行比较和匹配。正如您可能已经猜到的那样,这需要很长时间。为了给您一个想法,我尝试将 6 个非结构化名称与 700k 匹配,这需要三个小时。快速计算告诉我,如果这是脚本的平均速度,我将需要将近 3 个月的时间来处理 4000 家公司,这有点让人不知所措。我知道它必须进行数十亿次计算,而这不可能在几分钟内完成。但是,如果我能将这种情况减少到可能只有几天,我会非常高兴,而且我觉得这一定是可能的。
所以,我正在寻找加速这段代码的方法。通过最初将精确匹配与match() 函数配对,我已经设法对其进行了一些改进,这使得大约 500 家公司需要使用模糊匹配算法进行进一步处理。不过,至少可以说这需要很长时间。
我希望我能够清楚地解释自己!任何建议都将受到高度赞赏。
library(stringdist)
#Reading the two files to be compared and making sure that I'm dealing with characters
companies.unstructured <- read.csv(
"https://www.dropbox.com/s/opbk0s2q14l5c71/unstructured_companies.csv?dl=0",
sep = ";",
stringsAsFactors = FALSE
)
companies.structured <- read.csv(
"https://www.dropbox.com/s/kyi0rvz77frr7sd/structured_companies_w_CVR.csv?dl=0",
sep=";",
stringsAsFactors = FALSE
)
#Using the match function to match up all 100% identical companies to avoid unnecessary workload for the Jaro-Winkler loop
companies.unstructured$CVR = companies.structured$CVR[match(companies.unstructured$Company,
companies.structured$Company)]
companies.exact.match <- companies.unstructured[!is.na(companies.unstructured$CVR), ]
#Creating a subset to work on with the Jaro-Winkler loop.
companies.unstructured.na <- subset(companies.unstructured, is.na(CVR))
#And here's the loop measuring the distance between the company names using the Jaro-Winkler algorithm.
distance.methods<- c('jw')
dist.methods<-list()
for(m in 1:length(distance.methods))
{
dist.name.enh<-matrix(NA, ncol = length(companies.structured$Company),
nrow = length(companies.unstructured.na$Company))
for(i in 1:length(companies.structured$Company)) {
for(j in 1:length(companies.unstructured.na$Company)) {
dist.name.enh[j,i]<-stringdist(tolower(companies.structured[i,]$Company),
tolower(companies.unstructured.na[j,]$Company),
method = distance.methods[m])
}
}
dist.methods[[distance.methods[m]]]<-dist.name.enh
}
#matching up pairs of minimum distance
match.s1.s2.enh<-NULL
for(m in 1:length(dist.methods))
{
dist.matrix<-as.matrix(dist.methods[[distance.methods[m]]])
min.name.enh<-apply(dist.matrix, 1, base::min)
for(i in 1:nrow(dist.matrix))
{
s2.i<-match(min.name.enh[i],dist.matrix[i,])
s1.i<-i
match.s1.s2.enh<-rbind(data.frame(s2.i=s2.i,
s1.i=s1.i,
s1Company=companies.unstructured.na[s1.i,]$Company,
s2Company=companies.structured[s2.i,]$Company,
CVR=companies.structured[s2.i,]$CVR,
adist=min.name.enh[i],
method=distance.methods[m]),
match.s1.s2.enh)
}
}
编辑:以下是一些可以使用的数据示例:structured_companies_w_CVR 和 unstructured_companies
【问题讨论】:
-
请提供一个可重现的例子。读取数据时使用 stringsAsFactors = FALSE。将向量传递给函数而不是循环。
-
谢谢。通过可重现,您的意思是您希望我包含两个 csv 文件?
-
至少有一小部分类似的数据。提供我们运行您的代码所需的一切。
-
知道了。我编辑了原始帖子,使其现在包含两个链接
-
我已添加到您的代码的链接。它们无法工作,因为您将行名保存到 csv 文件。删除 rownames 列或为其命名。
标签: r fuzzy-comparison jaro-winkler