Scalaの配列(リスト)の各要素の出現個数をカウントする
Scalaの配列(リスト)の各要素の出現個数をカウントする方法について調べたのでまとめます。Pythonであればcollections.Counterやcountメソッドで実現できることを、Scalaでは関数型言語の思想に近い形で記述することができます。記事の後半ではおまけとして、配列内のカテゴリ変数の分かれ方を表す指標であるジニ係数(Gini Score)の算出方法についても書いています。
Scalaの配列(リスト)の各要素の出現個数をカウント
次のような長さ10の文字列配列があるとします。
val s = Seq("A", "A", "A", "B", "A", "C", "A", "A", "A", "B")
この配列中の各要素の出現回数は次のように求めることができます。なお、ここでの出力はMap型になります。
val cntMap = s.groupBy(identity).mapValues(_.size) cntMap: Map(A -> 7, C -> 1, B -> 2)
各要素の個数についてアクセスしたい場合は次のように書きます。要素“A”の個数は7個であることがわかります。
cntMap("A") res: 7
配列内のカテゴリ変数のばらつき度合い(分散)をジニ係数で求める
ジニ係数とは配列内の各要素がどの程度ばらついているかを求める指標であり、0から1の範囲をとります。すべての要素が”A”であればジニ係数は0になり、すべての要素が互いに異なる場合は1に近い値をとります。
ジニ係数の詳細については次の記事に記載しています。
http://hktech.hatenablog.com/entry/2018/10/05/004235
ジニ係数は次の式で求めることができます。
ここでは配列全体の要素数が必要となるので、次のように求めます。
val seqLen = s.size
算出式中の部分については、次のように求められます。
Math.pow(v.toDouble/seqLen, 2)
最終的なジニ係数の算出はfoldLeft関数を使って以下のように書くことができます。
val giniScore = 1.0 - cntMap.values.foldLeft(0.0)((sum, v) => sum + Math.pow(v.toDouble/seqLen, 2))