2

> 800k 行のデータセットがあります (例):

id     fieldA       fieldB              codeA   codeB
120    Similar one  addrs example1      929292  0006
3490   Similar oh   addrs example3      929292  0006
2012   CLOSE CAA    addrs example10232  kkda9a  0039
9058   CLASE CAC    addrs example01232  kkda9a  0039
9058   NON DONE     addrs example010193 kkda9a  0039
48848  OOO AD ADDD  addrs example18238  uyMMnn  8303

フィールド ID は一意の ID です。フィールド codeA と codeB は同じでなければなりませんが、フィールド fieldA と fieldB にはレーベンシュタイン距離または同様の関数が必要です。それに基づいて、どの行が非常に似ているかを見つける必要があります。出力は、次の行にある可能性があります。

   codeA    codeB Similar
   929292   0006  120;3490
   kkda9a   0039  2012;9058
   kkda9a   0039  9058
   uyMMnn   8303  48848

コード A とコード B のような 2 つの制約がある場合、このような大きなデータセットの距離行列は機能せず、あまり意味がありません。1つのアプローチは、codeA-codeBで分割するplyr関数になると思いますが、その後行き詰まっています

明確にするために、fieldAとfieldB の両方で類似性が高く、codeAcodeB で完全に一致するすべての行をグループ化したいと考えています。


編集:

David DeWert のアイデアに従って、この行に沿った何かが各 codeA-codeB グループで機能するように見えます。

library(stringdist)
clustering<-function(x){
  if(nrow(x)>1){{d<-stringdistmatrix(paste(x$fieldA,x$fieldB),paste(x$fieldA,x$fieldB),method = "qgram")
  rownames(d)<-x$id
  hc <- hclust(as.dist(d))
  #I need to evaluate correctly this cutting
  res<-cutree(hc,h=5)
  #This returns a list, one element for each cluster found and a named vector inside with the elements
  return(res)
  }else{
  res<-1
  names(res)<-x$id
  return(res)
  }
}

ここで、データフレームを codeA-codeB グループに分割し、この関数をそれらに適用する方法を見つける必要があります。


EDIT2:

以前の関数クラスタリングと plyr パッケージを使用して、これに対して「十分な」アプローチを管理しました。

result<-dlply(testDF,.(codeA,codeB),clustering)

これにより、次のような「codeA、codeBによるグループ」のそれぞれを含むリストが作成されます。

$`929292.0006`
 120 3490 
   1    1 

$kkda9a.0039
2012 9058 9058 
   1    1    2 

$uyMMnn.8303
48848 
    1 

attr(,"split_type")
[1] "data.frame"
attr(,"split_labels")
   codeA codeB
1 929292  0006
2 kkda9a  0039
3 uyMMnn  8303

これは、codeA と codeB によって作成されたグループを fieldA と fieldB で効果的にクラスター化します。これで目的の出力が得られませんが、より良い解決策が得られないため、やらなければなりません。これに対する私の最大の不満は、plyr 関数の性質上、グループごとに複数の行を取得できないことです (これは完全に理にかなっています)。そのため、データフレームの代わりにリストを結果として使用する必要があります。問題は、データセットが非常に大きく (このように)、plyr がうまく機能しない場合に発生します...そして代替の dplyr パッケージはリストの結果と互換性がありません...まあ。

4

1 に答える 1

4

「codeAB」という新しいフィールドを作成して、次のように codeA-codeB の一致に従ってデータを分割します。

data$codeAB <- factor(apply( data[ , c(4,5) ] , 1 , paste , collapse = "-" ))

次に、それぞれlevels(data$codeAB) を Damerau-Levenshtein でクラスター化します。ELKI http://en.wikipedia.org/wiki/ELKIは、距離行列を構築せずに大規模なデータ コレクションをクラスタリングするのに適していると人々は示唆しているようです。

誰かが ELKI の DL メトリックについても質問していました: ELKI を使用した文字列データのクラスタリング

お役に立てば幸いです。

于 2015-02-11T19:02:32.520 に答える