(この記事は「fukuoka.ex x ザキ研 Advent Calendar 2017」の14日目です)
昨日は、@kobatako さんの「GraphQL for Elixir#2 リクエストとレスポンスの値について考える」でした
fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます
この連載の、前回までの記事は、以下になります
|> 関数型でデータサイエンス#1:様々なデータをインプットする
|> 関数型でデータサイエンス#2:インプットしたデータを変換する
今回は、「データ前処理」の続きとして、「インプットしたデータの集約」について解説します
ElixirのEnumの中では、やや使いこなしが難しい、Enum.group_by()を、SQLのGROUP BYと同じように使うサンプルとしても活用できるコラムです
サンプルデータ等は、前回と同じものを使います
それでは、Phoenixサーバーを起動し、ブラウザで「http://localhost:4000
」のWebページが見れる状態にしたら、以下を試していきましょう
お礼:6/22のfukuoka.ex#11、おかげさまで盛り上がりました
fukuoka.ex設立から1周年記念となる、fukuoka.ex#11「DB/データサイエンスにコネクトするElixir」、過去最大規模の50名オーバーで、コンテンツもメチャクチャ濃く、とても盛り上がりました
データ集約
データ集約としては、以下がポピュラーです
- グループ化
- カウント
- 合計
- 最大値
- 最小値
- 平均値
- 中央値
- パーセンタイル
- 分散値
- 標準偏差
- 最頻値
グループ化
同じキー値を持つデータをリストアップするには、まずEnum.group_by()で「キー値」と「データリスト」という形式でグルーピングし、キー値とデータリストの各々に列名を付け直す操作をします
…
datas = result
|> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) )
|> Enum.map( &(
%{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 ) |> Lst.to_csv } ) )
…
カウント
カウントは、グルーピング後のキー値とデータリストの各々に列名を付け直す際、データリストにEnum.count()することで取得できます
…
datas = result
|> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) )
|> Enum.map( &(
%{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 ) |> Enum.count } ) )
合計
合計は、グルーピング後のキー値とデータリストの各々に列名を付け直す操作時、データリストをEnum.reduce()で足しこんでいけば取得できます
…
datas = result
|> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) )
|> Enum.map( &(
%{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 )
|> Enum.reduce( 0, fn( n, acc ) -> acc + String.to_integer( n ) end ) } ) )
…
最大値・最小値
最大値・最小値は、グルーピング後のキー値とデータリストの各々に列名を付け直す操作時、データリストにEnum.max()もしくはEnum.max()を行うことで取得できます
…
datas = result
|> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) )
|> Enum.map( &(
%{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 )
|> Enum.map( fn( n ) -> String.to_integer( n ) end ) |> Enum.max } ) )
…
…
datas = result
|> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) )
|> Enum.map( &(
%{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 )
|> Enum.map( fn( n ) -> String.to_integer( n ) end ) |> Enum.min} ) )
…
平均値・中央値・パーセンタイル・分散値・標準偏差・最頻値
これらの統計系は、ElixirのEnumが、標準で計算する機能を持っていないため、次回、自前で関数を作りつつ、対応してみます
終わり
今回は、「データ前処理」の続きとして、「インプットしたデータの集約」の前半について取り上げました
次回は、「インプットしたデータの集約」の後半を行います
明日は @yukq16 さんの「2次元リスト加算関数」です
p.s.「いいね」よろしくお願いします
よろしければ、ページ左上の や のクリックをお願いしますー
ここの数字が増えると、書き手としては「ウケている」という感覚が得られ、連載を更に進化させていくモチベーションになりますので、もっとElixirネタを見たいというあなた、私たちと一緒に盛り上げてください!