この記事は、Elixir Advent Calendar 2023 シリーズ14 の18日目です
【本コラムは、5分で読め、3分で試せます】
piacere です、ご覧いただいてありがとございます
Elixirはデータ分析が得意な言語ですが、その中でも「発生頻度の計算」は利用シーンが多い一方、古いElixirには該当関数が無かった歴史を紹介しつつ、使い方を解説します
Enum.frequencies
、Enum.frequencies_by
リストから発生頻度を算出する関数である、Enum.frequencies
と Enum.frequencies_by
は、Elixir 1.9までは存在しておらず、自前で作る必要がありました
リストにある値の発生頻度
都道府県の先頭文字の発生頻度を求めます
iex> pref = ["北海道", "青森", "岩手", "宮城", "秋田", "山形", "福島",
"茨城", "栃木", "群馬", "埼玉", "千葉", "東京", "神奈川",
"新潟", "富山", "石川", "福井", "山梨", "長野", "岐阜", "静岡",
"愛知", "三重", "滋賀", "京都", "大阪", "兵庫", "奈良",
"和歌山", "鳥取", "島根", "岡山", "広島", "山口", "徳島",
"香川", "愛媛", "高知", "福岡", "佐賀", "長崎", "熊本", "大分",
"宮崎", "鹿児島", "沖縄"]
iex> pref |> Enum.map(& String.first(&1)) |> Enum.frequencies
%{
"滋" => 1,
"北" => 1,
"徳" => 1,
…
"鹿" => 1,
"佐" => 1,
"千" => 1
}
1件を除外します
iex> pref |> Enum.map(& String.first(&1)) |> Enum.frequencies |> Enum.reject(& elem(&1, 1) == 1)
[{"山", 3}, {"大", 2}, {"福", 3}, {"愛", 2}, {"宮", 2}, {"長", 2}]
一部の値を含む発生頻度
先頭文字に限らず、「福」を持つ都道府県の発生頻度を求めるには、Enum.frequencies_by
に抽出用関数を指定すればOKです
iex> pref |> Enum.frequencies_by(& String.contains?(&1, "福"))
「福」を持つ都道府県は、3つあるようです
%{false: 44, true: 3}
「山」を持つ都道府県は、6つもあるようです
iex> pref |> Enum.frequencies_by(& String.contains?(&1, "山"))
%{false: 41, true: 6}
「山」で始まる都道府県は、正規表現を使っても求められ、6つもあるようです
iex> pref |> Enum.frequencies_by(& Regex.match?(~r/^山/, &1))
%{false: 41, true: 6}
「島」で終わる都道府県も正規表現で求められ、4つあるようです
iex> pref |> Enum.frequencies_by(& Regex.match?(~r/島$/, &1))
%{false: 45, true: 2}
値を確認したい場合
Enum.frequencies_by
と同じ条件を、Enum.group_by
に渡すと、Enum.frequencies
のように発生頻度の元となった値を拾うこともでき、true
のみを抽出すればマッチした値のみを拾えます
iex> pref |> Enum.group_by(& String.contains?(&1, "福"))
%{
false: ["北海道", "青森", "岩手", "宮城", "秋田", "山形",
"茨城", "栃木", "群馬", "埼玉", "千葉", "東京", "神奈川",
"新潟", "富山", "石川", "山梨", "長野", "岐阜", "静岡",
"愛知", "三重", "滋賀", "京都", "大阪", "兵庫", "奈良",
"和歌山", "鳥取", "島根", "岡山", "広島", "山口", "徳島",
"香川", "愛媛", "高知", "佐賀", "長崎", "熊本", "大分",
"宮崎", "鹿児島", "沖縄"],
true: ["福島", "福井", "福岡"]
}
iex> pref |> Enum.group_by(& String.contains?(&1, "福")) |> Map.get(true)
["福島", "福井", "福岡"]