LoginSignup
9
0

【TIPS】リストの値から発生頻度を算出する

Last updated at Posted at 2023-12-24

この記事は、Elixir Advent Calendar 2023 シリーズ14 の18日目です


【本コラムは、5分で読め、3分で試せます】

piacere です、ご覧いただいてありがとございます :bow:

Elixirはデータ分析が得意な言語ですが、その中でも「発生頻度の計算」は利用シーンが多い一方、古いElixirには該当関数が無かった歴史を紹介しつつ、使い方を解説します

Enum.frequenciesEnum.frequencies_by

リストから発生頻度を算出する関数である、Enum.frequenciesEnum.frequencies_by は、Elixir 1.9までは存在しておらず、自前で作る必要がありました
image.png

Elixir 1.10からは標準搭載されています
image.png

リストにある値の発生頻度

都道府県の先頭文字の発生頻度を求めます

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)
["福島", "福井", "福岡"]
9
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
0