8

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

2回表示されます(スペルミスあり)。データセット全体の各候補には、一意の数値候補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:今は良い速度で実行されています。問題は、すべてのステップでの多くの要因との比較でした(それを指摘してくれてありがとう、BlueMagister)。1つのグループ(つまり都市)の候補者のみとの比較を減らすと、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)
4

2 に答える 2

4

これが私のショットです。あまり効率的ではないかもしれませんが、仕事はうまくいくと思います。それ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]
于 2012-10-21T16:55:51.977 に答える
3

さて、効率に焦点が当てられていることを考えると、私は次のことを提案します。

まず、第一原理からの効率の順に、正確なマッチングはgrepよりもはるかに高速であり、ファジーgrepよりも高速であると予測できることに注意してください。完全に一致し、残りの観測値のファジーgrep。

次に、ベクトル化してループを回避します。applyコマンドは必ずしも高速ではないため、可能であればネイティブのベクトル化に固執します。すべてのコマンドはネイティブにベクトル化されていますが、各要素を他の要素のベクトルと比較するためのまたはループをgrep回避するのは困難です。*ply

第三に、外部情報を使用して問題を絞り込みます。各都市または州内でのみ名前のあいまい一致を実行します。これにより、たとえば、実行する必要のある比較の数が大幅に削減されます。

最初の原則と3番目の原則を組み合わせることができます。各文字列の最初の文字を完全に一致させてから、その中であいまい一致を試みることもできます。

于 2012-10-21T17:12:15.450 に答える