2017-03-14 11 views
1

私は文字列一致を行う必要がある大きなデータセットを持っています。私はこのサイトからいくつかの非常に便利な投稿を持っていて、私のデータセットの文字列マッチングを行う関数を作成しました。サンプルデータとコードを貼り付けています。R関数は列の値に基づいて繰り返されます

サンプルデータ

Address1 <- c("786, GALI NO 5, XYZ","rambo, 45, strret 4, atlast, pqr","23/4, 23RD FLOOR, STREET 2, ABC-E, PQR","45-B, GALI NO5, XYZ","HECTIC, 99 STREET, PQR") 
AREACODE <- c('10','10','14','20','30') 
Year1 <- c(2001:2005) 

Address2 <- c("abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR","abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR") 
Year2 <- c(2001:2010) 
AREA_CODE <- c('10','10','10','20','30','40','50','61','64', '99') 

data1 <- data.table(Address1, Year1, AREACODE) 
data2 <- data.table(Address2, Year2, AREA_CODE) 
data2[, unique_id := sprintf("%06d", 1:nrow(data2))] 

CODE

fn.fuzzymatch<-function(dat1,dat2,string1,string2,meth){ 

    dist.name<-stringdistmatrix(dat1[[string1]],dat2[[string2]],method = meth) 

    min.name<-apply(dist.name, 1, min) 

    match.s1.s2<-NULL 
    for(i in 1:nrow(dist.name)) 
    { 
    s2.i<-match(min.name[i],dist.name[i,]) 
    s1.i<-i 
    match.s1.s2<-rbind(data.frame(s1_row=s1.i,s2_row=s2.i,s1name=dat1[s1.i,][[string1]],s2name=dat2[s2.i,][[string2]], dist=min.name[i]),match.s1.s2) 
    } 
    output <- (match.s1.s2)[order(match.s1.s2$s1_row),] 
    return(output) 
} 


match_50 <- fn.fuzzymatch(data1,data2,"Address1","Address2","dl") 

これは、国レベルでのデータのために正常に動作しているが、その後私は、地域レベルでの複数のデータファイルがあり、各領域であります複数の領域を有する。各地域のAreacodeは、AREACODE data1の変数とAREA_CODE data2の変数で利用できます。私は、文字列マッチングは、エリアごとに行われ、出力はそのエリアコードを持っている

  • 出力は、その領域内のすべてのエリアコードのために統合し、各地域のために返され

    1. ように、私の機能を更新したいです。

    私はsplitを使用してデータファイルをリストに変換して使用し、rbindlistを使用して結合しましたが、成功することができず、さまざまな種類のエラーが発生していました。私はこれを行う方法があると確信していますが、それを得ることはできません。私はいくつかの提案ができることを願っています。

  • +0

    あなたはこれまでにしようとしているコードを共有してもらえますか? Data1とData2は、データが地域レベルでどのように見えるかを表していますか? –

    +0

    @JuanBosco、はいdat1とdat2は、データが地域レベルでどのように見えるかを表します。このように私は10の地域のための複数のデータファイルを持っています。私はこの現在の機能を10回呼んでいました。しかし今、私は各地域のためのチェックを行い、地域のための出力を得る必要があります。各地域は10〜40の異なるエリアを持つことができ、合計で190のユニークエリアがあります。 – user1412

    +0

    あなたの関数は、データセットのペアを取り、それらのオペレーションを実行することがわかります。各エリアをチェックするとどういう意味ですか?第1のデータセットの各エリア、第2のデータセットのエリアのすべての組み合わせ、要するに、あなたの期待される出力は? あなたの現在の機能を使っていくつかの可能な出力を達成できると思いますが、私はあなたが必要とするものを完全には分かっていません。 –

    答えて

    0

    おそらく適用機能を使用して、異なる地域の別々のデータファイルを繰り返すことができますが、ここではprevious questionへの回答に基づくfuzzyjoin解決策があります。

    Addressに一致するアドレスはstringdistで、AreaCodeは正確に一致する必要があります(==)。私はまた、デモのためだけにyear2が>= year1でなければならないと指定しました。

    最後に、私はdplyr::group_bydplyr::top_nを使用して最小距離のマッチを得ました。そして、マッチングマッチで何をするかを仮定しなければなりませんでした。

    データ:

    Address1 <- c("786, GALI NO 5, XYZ","rambo, 45, strret 4, atlast, pqr","23/4, 23RD FLOOR, STREET 2, ABC-E, PQR","45-B, GALI NO5, XYZ","HECTIC, 99 STREET, PQR") 
    AREACODE <- c('10','10','14','20','30') 
    Year1 <- c(2001:2005) 
    
    Address2 <- c("abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR","abc, pqr, xyz","786, GALI NO 4 XYZ","45B, GALI NO 5, XYZ","del, 546, strret2, towards east, pqr","23/4, STREET 2, PQR") 
    Year2 <- c(2001:2010) 
    AREA_CODE <- c('10','10','10','20','30','40','50','61','64', '99') 
    
    data1 <- data.table(Address1, Year1, AREACODE) 
    data2 <- data.table(Address2, Year2, AREA_CODE) 
    data2[, unique_id := sprintf("%06d", 1:nrow(data2))] 
    

    ソリューション:

    library(fuzzyjoin, quietly = TRUE); library(dplyr, quietly = TRUE) 
    
    # First, need to define match_fun_stringdist 
    # Code from stringdist_join from https://github.com/dgrtwo/fuzzyjoin 
    match_fun_stringdist <- function(v1, v2) { 
    
        # for some reason, I couldn't pass these parameters in from fuzzy_join, 
        # so I set them here. 
        ignore_case = FALSE 
        method = "dl" 
        max_dist = 99 
        distance_col = "dist" 
    
        if (ignore_case) { 
        v1 <- stringr::str_to_lower(v1) 
        v2 <- stringr::str_to_lower(v2) 
        } 
    
        # shortcut for Levenshtein-like methods: if the difference in 
        # string length is greater than the maximum string distance, the 
        # edit distance must be at least that large 
    
        # length is much faster to compute than string distance 
        if (method %in% c("osa", "lv", "dl")) { 
        length_diff <- abs(stringr::str_length(v1) - stringr::str_length(v2)) 
        include <- length_diff <= max_dist 
    
        dists <- rep(NA, length(v1)) 
    
        dists[include] <- stringdist::stringdist(v1[include], v2[include], method = method) 
        } else { 
        # have to compute them all 
        dists <- stringdist::stringdist(v1, v2, method = method) 
        } 
        ret <- dplyr::data_frame(include = (dists <= max_dist)) 
        if (!is.null(distance_col)) { 
        ret[[distance_col]] <- dists 
        } 
        ret 
    } 
    
    # Finally, call fuzzy_join 
    fuzzy_join(data1, data2, 
          by = list(x = c("Address1", "AREACODE", "Year1"), y = c("Address2", "AREA_CODE", "Year2")), 
          match_fun = list(match_fun_stringdist, `==`, `<=`), 
          mode = "left" 
          ) %>% 
        group_by(Address1, Year1, AREACODE) %>% 
        top_n(1, -Address1.dist) %>% 
        top_n(1, Year2) %>% 
        select(unique_id, Address1.dist, everything()) 
    
    関連する問題