2012-11-26 109 views
2

我還是不太熟練使用Scala,但我用它來處理一些數據,這是我讀入從文件導入數據結構如下:地圖轉換(計算標籤頻率)

Map[Id, (Set[Category], Set[Tag])]

其中

type Id = String 

type Category = String 

type Tag = String 

從本質上講,在Map每個鍵是與一組類別和一組標籤相關聯的實體的唯一的ID。

我的問題是:這是最好的(=最高效地道)的方式來計算:

  • 標籤在所有實體頻率(type TagsFrequencies = Map[Tag, Double]
  • 每個類別標籤的頻率( Map[Category, TagsFrequencies]

這裏是我的嘗試:

def tagsFrequencies(tags: List[Tag]): TagsFrequencies = 
    tags.groupBy(t => t).map(
    kv => (kv._1 -> kv._2.size.toDouble/tags.size.toDouble)) 

def computeTagsFrequencies(data: Map[Id, (Set[Category], Set[Tag])]): TagsFrequencies = { 
    val tags = data.foldLeft(List[Tag]())(
    (acc, kv) => acC++ kv._2._2.toList) 
    tagsFrequencies(tags) 
} 

def computeTagsFrequenciesPerCategory(data: Map[Id, (Set[Category], Set[Tag])]): Map[Category, TagsFrequencies] = { 

    def groupTagsPerCategory(data: Map[Id, (Set[Category], Set[Tag])]): Map[Category, List[Tag]] = 
    data.foldLeft(Map[Category, List[Tag]]())(
     (acc, kv) => kv._2._1.foldLeft(acc)(
     (a, category) => a.updated(category, kv._2._2.toList ++ a.getOrElse(category, Set.empty).toList))) 

    val tagsPerCategory = groupTagsPerCategory(data) 
    tagsPerCategory.map(tpc => (tpc._1 -> tagsFrequencies(tpc._2))) 
} 

作爲一個例子,考慮

val data = Map(
    "id1" -> (Set("c1", "c2"), Set("t1", "t2", "t3")), 
    "id2" -> (Set("c1"), Set("t1", "t4"))) 

則:

所有實體標籤的頻率是:每個類別

Map(t3 -> 0.2, t4 -> 0.2, t1 -> 0.4, t2 -> 0.2) 

和標籤的頻率是:

Map(c1 -> Map(t3 -> 0.2, t4 -> 0.2, t1 -> 0.4, t2 -> 0.2), c2 -> Map(t3 -> 0.3333333333333333, t1 -> 0.3333333333333333, t2 -> 0.3333333333333333)) 

回答

2

這裏是對成語的重寫,不一定是效率。我會想辦法讓你的第一個方法稍微更一般的(在Iterable參數),使用identity代替t => t,並使用mapValues

def tagsFrequencies(tags: Iterable[Tag]): TagsFrequencies = 
    tags.groupBy(identity).mapValues(_.size/tags.size.toDouble) 

正因爲如此,現在採取任何Iterable[Tag],你可以用它來清理第二方法:

def computeTagsFrequencies(data: Map[Id, (Set[Category], Set[Tag])]) = 
    tagsFrequencies(data.flatMap(_._2._2)) 

同樣地,對於最後一種方法:

def computeTagsFrequenciesPerCategory(data: Map[Id, (Set[Category], Set[Tag])]) = 
    data.values.flatMap { 
    case (cs, ts) => cs.map(_ -> ts) 
    }.groupBy(_._1).mapValues(v => tagsFrequencies(v.flatMap(_._2))) 

這些通道無時代應該以任何有意義的方式影響績效,但是您當然應該在自己的應用程序中進行基準測試。