簡體   English   中英

通過模糊匹配名稱創建唯一ID(通過使用R的agrep)

[英]Create a unique ID by fuzzy matching of names (via agrep using R)

使用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 CEZAR FERREIRA DE ARAUJO

PAULO CESAR FERREIRA DE ARAUJO

出現兩次(拼寫錯誤)。 應為整個數據集中的每個候選者分配唯一的數字候選ID。 數據集相當大(5500個城市,大約100K條目),因此稍微有效的編碼會有所幫助。 有關如何實現這一點的任何建議?

編輯:這是我嘗試(在迄今為止的評論的幫助下)在實現手頭任務時非常緩慢(低效)。 有關改進的建議嗎?

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:現在以良好的速度運行。 問題在於每一步都與許多因素進行比較(感謝你指出這一點,Blue Magister)。 將比較減少到只有一組中的候選者(即一個城市),在5秒內運行命令,持續80,000行 - 這是我可以忍受的速度。

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)

這是我的鏡頭。 它可能效率不高,但我認為它可以完成工作。 我認為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]

好吧,鑒於重點是效率,我建議如下。

首先,請注意,從第一原理的效率開始,我們可以預測精確匹配將比grep快得多,后者將比模糊grep更快。 如此精確匹配,然后模糊grep用於剩余的觀察。

其次,矢量化和避免循環。 apply命令不一定更快,因此如果可以,請堅持使用本機矢量化。 所有grep命令都是本機矢量化的,但是很難避免使用*ply或循環來將每個元素與其他元素的矢量進行比較以匹配。

第三,利用外部信息縮小問題范圍。 例如,只對每個城市或州內的名稱進行模糊匹配,這將大大減少必須進行的比較次數。

您可以結合第一和​​第三原則:您甚至可以嘗試在每個字符串的第一個字符上進行精確匹配,然后在其中進行模糊匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM