Crie um ID exclusivo por correspondência fuzzy de nomes (via agrep usando R)

Usando R, estou tentando combinar os nomes das pessoas em um conjunto de dados estruturado por ano e cidade. Devido a alguns erros de ortografia, a correspondência exata não é possível, por isso estou tentando usar agrep () para nomes de correspondência difusos.

Um pedaço de amostra do conjunto de dados é estruturado da seguinte forma:

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")) ))

A versão pura:

  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

Eu gostaria de verificar cada cidade separadamente, se há candidatos aparecendo em vários anos. Por exemplo. no exemplo,

PAULO CEZAR FERREIRA DE ARAUJO

PAULO CESAR FERREIRA DE ARAUJO

aparece duas vezes (com um erro de ortografia). Cada candidato em todo o conjunto de dados deve receber um ID de candidato numérico exclusivo. O conjunto de dados é razoavelmente grande (5500 cidades, aproximadamente 100 mil entradas), de modo que uma codificação eficiente seria útil. Alguma sugestão de como implementar isso?

EDIT: Aqui é minha tentativa (com ajuda dos comentários até agora) que é muito lenta (ineficiente) para alcançar a tarefa em mãos. Alguma sugestão quanto a melhorias para isso?

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)

EDIT 2: Agora executando a boa velocidade. Problema foi a comparação com muitos fatores a cada passo (Obrigado por apontar isso, Blue Magister). Reduzir a comparação para apenas os candidatos em um grupo (ou seja, uma cidade) executa o comando em 5 segundos para 80.000 linhas - uma velocidade com a qual posso conviver.

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)

questionAnswers(2)

yourAnswerToTheQuestion