(通过使用AGREP R)创建由名称的模糊匹配的唯一ID(Create a unique ID by

2019-07-01 15:02发布

使用R,我想通过一年的城市构成的数据集上的人的名字相匹配。 由于一些拼写错误,精确匹配是不可能的,所以我试图用AGREP()来模糊匹配的名字。

数据集的样品块的结构如下:

df <- data.frame(matrix( c("1200013","1200013","1200013","1200013","1200013","1200013","1200013","1200013",                             "1996","1996","1996","1996","2000","2000","2004","2004","AGUSTINHO FORTUNATO FILHO","ANTONIO PEREIRA NETO","FERNANDO JOSE DA COSTA","PAULO CEZAR FERREIRA DE ARAUJO","PAULO CESAR FERREIRA DE ARAUJO","SEBASTIAO BOCALOM RODRIGUES","JOAO DE ALMEIDA","PAULO CESAR FERREIRA DE ARAUJO"), ncol=3,dimnames=list(seq(1:8),c("citycode","year","candidate")) ))

整洁的版本:

  citycode year                      candidate
1  1200013 1996      AGUSTINHO FORTUNATO FILHO
2  1200013 1996           ANTONIO PEREIRA NETO
3  1200013 1996         FERNANDO JOSE DA COSTA
4  1200013 1996 PAULO CEZAR FERREIRA DE ARAUJO
5  1200013 2000 PAULO CESAR FERREIRA DE ARAUJO
6  1200013 2000    SEBASTIAO BOCALOM RODRIGUES
7  1200013 2004                JOAO DE ALMEIDA
8  1200013 2004 PAULO CESAR FERREIRA DE ARAUJO

我想在每个城市分别检查,是否有出现在数年的候选人。 例如,在示例中,

PAULO塞萨尔·费雷拉·德阿劳霍

保罗·塞萨尔费雷拉·德阿劳霍

出现两次(带拼写错误)。 整个数据集中各候选应被分配一个唯一的数字考生ID。 该数据集是相当大(5500个城市,约10万项),所以有点高效的编码将是有益的。 任何建议,如何实现这一点?

编辑:这是我尝试(从迄今的评论帮助)是实现手头的任务非常慢(低效率)。 任何建议,改进呢?

f <- function(x) {matches <- lapply(levels(x), agrep, x=levels(x),fixed=TRUE, value=FALSE)
                  levels(x) <- levels(x)[unlist(lapply(matches, function(x) x[1]))]
                  x
                }

temp <- tapply(df$candidate, df$citycode, f, simplify=TRUE)
df$candidatenew <- unlist(temp)
df$spellerror <- ifelse(as.character(df$candidate)==as.character(df$candidatenew), 0, 1)

编辑2:现在,在良好的运行速度。 问题是比较许多因素在每一步(感谢指出了这一点,蓝魔导师)。 减少的比较仅在一组(即市)考生运行80,000线在5秒内命令 - 我能忍受的速度。

df$candidate <- as.character(df$candidate)

f <- function(x) {x <- as.factor(x)
                  matches <- lapply(levels(x), agrep, x=levels(x),fixed=TRUE, value=FALSE)
                  levels(x) <- levels(x)[unlist(lapply(matches, function(x) x[1]))]
                  as.character(x)
                }

temp <- tapply(df$candidate, df$citycode, f, simplify=TRUE)
df$candidatenew <- unlist(temp)
df$spellerror <- ifelse(as.character(df$candidate)==as.character(df$candidatenew), 0, 1)

Answer 1:

这里是我的投篮吧。 它可能不是很有效,但我认为它会完成这项工作。 我认为df$candidates是阶级因素。

#fuzzy matches candidate names to other candidate names
#compares each pair of names only once
##by looking at names that have a greater index
matches <- unlist(lapply(1:(length(levels(df[["candidate"]]))-1),
    function(x) {max(x,x + agrep(
        pattern=levels(df[["candidate"]])[x], 
        x=levels(df[["candidate"]])[-seq_len(x)]
    ))}
))
#assigns new levels (omits the last level because that doesn't change)
levels(df[["candidate"]])[-length(levels(df[["candidate"]]))] <- 
    levels(df[["candidate"]])[matches]


Answer 2:

好了,因为重点是效率,我建议如下。

首先,请注意,从第一原理效率的订单,我们可以预测,精确匹配会比grep的,这将是比模糊grep的速度快得多。 因此精确匹配,则模糊grep命令剩下的意见。

二,矢量化和避免环路。 该apply的命令并不一定会更快,所以如果你能坚持到本机矢量。 所有grep命令本地矢量化,但是这将是难以避免*ply或回路的每个元素和别人比较匹配到的载体。

第三,利用外界信息以缩小问题了。 仅在每个城市或国家,这将大大减少,必须进行比较的次数,例如请在名称模糊匹配。

您可以结合第一和​​第三原则:你甚至可以尝试在每个字符串的第一个字符精确匹配,那么内的模糊匹配。



文章来源: Create a unique ID by fuzzy matching of names (via agrep using R)