2016-12-20 49 views
1

我在一列中有100K個名字。我需要比較每個人是否相同(D'souza,D'souza)或幾乎相同(D'souza,Dsouza)。如何使用scala比較一行與火花中的所有其他行

我試着將cassandra表讀入RDD中,並且將列的笛卡爾乘積與它自己組成一個元組。但由於列大小爲100K,因此會導致巨大的RDD,並最終導致火花工作掛起。

下面是我的代碼:

val valueRdd = sc.cassandraTable("keyspace", "some_table") 
    val dataRDD = valueRdd 
    .map(row => { 
     (
     row 
      .getStringOption("name") 
      .get, 

    }).cache() 

    val cartesianResult = dataRDD cartesian dataRDD 
    //Followed by some compare logic. May be soundex or some other library or some fuzzy logic. 

的這裏的問題是,笛卡爾的結果將是100K * 100K這是不理想的秩序。有沒有更好的方法來做到這一點?

問題陳述是識別給定數據集中的同胞。數據集將包含100K +數據。

+0

你想對重複/相似名稱做什麼?重複數據刪除?推斷數據?或者你是否真的需要每一對可能的名字,以及它們是否相同/相似? –

+0

想法是識別兄弟姐妹。在這種情況下,名稱可以有很小的變化,但最後指的是同一個人。例如:D'souza,Dsouza是同一個人,儘管名稱與「'」不同。所以我在確定了所有這些變體之後,用一個通用的名字替換了所有的兄弟姐妹。例如:D'souza,Dsouza或D souza或類似名稱的所有實例都將有一個俗名Dsouza。 – Ankur

回答

4

這份名單是足夠小,你可以在列表轉換成廣播變量,讓每個節點進行比較時的RDD到廣播列表的一部分:

val valueRddBC =sc.broadcast(valueRdd.collect()) 
val similarPairsRdd = valueRdd.flatMap(x => 
    valueRddBc.value.filter(y => dist(x,y) > threshold) 
        .map(y => (x,y))) 

100K足夠小,雖然你可以做如果你想要的話,在驅動程序中的整個事情(如果dist功能不昂貴,這可能會更快)。

如果RDD非常大,您可以將項目映射到某種指紋,以便通過諸如LSH(本地敏感散列)之類的策略忽略大多數不相關的項目。這是近似最近鄰居算法,它給出了O(1)以找到最近的項目。

0

你的比較函數做比較名稱更復雜嗎?如果你所做的只是刪除空格和撇號,你可以簡單地將RDD轉換成一個RDD對,該RDD由名稱的簡化版本控制,然後使用groupBy對相似的名稱進行分組。例如:

scala> val rdd = sc.parallelize(List("d'souza", "d souza", "Dsouza")) 
scala> rdd.map{ 
    |  case x => x.replaceAll(" ", "").replaceAll("'","").toLowerCase -> x 
    | }.groupByKey.collect 
res3: Array[(String, Iterable[String])] = Array((dsouza,CompactBuffer(d'souza, d souza, Dsouza))) 
相關問題