LoginSignup
10
2

More than 5 years have passed since last update.

関数型でデータサイエンス#3:インプットしたデータを集約する①

Last updated at Posted at 2018-07-01

(この記事は「fukuoka.ex x ザキ研 Advent Calendar 2017」の14日目です)

昨日は、@kobatako さんの「GraphQL for Elixir#2 リクエストとレスポンスの値について考える」でした


fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます:bow:

この連載の、前回までの記事は、以下になります
 |> 関数型でデータサイエンス#1:様々なデータをインプットする
 |> 関数型でデータサイエンス#2:インプットしたデータを変換する

今回は、「データ前処理」の続きとして、「インプットしたデータの集約」について解説します

ElixirのEnumの中では、やや使いこなしが難しい、Enum.group_by()を、SQLのGROUP BYと同じように使うサンプルとしても活用できるコラムです

サンプルデータ等は、前回と同じものを使います

それでは、Phoenixサーバーを起動し、ブラウザで「http://localhost:4000」のWebページが見れる状態にしたら、以下を試していきましょう


:shamrock::shamrock::shamrock: お礼:6/22のfukuoka.ex#11、おかげさまで盛り上がりました :shamrock::shamrock::shamrock:

fukuoka.ex設立から1周年記念となる、fukuoka.ex#11「DB/データサイエンスにコネクトするElixir」、過去最大規模の50名オーバーで、コンテンツもメチャクチャ濃く、とても盛り上がりました

image.png

データ集約

データ集約としては、以下がポピュラーです

  • グループ化
  • カウント
  • 合計
  • 最大値
  • 最小値
  • 平均値
  • 中央値
  • パーセンタイル
  • 分散値
  • 標準偏差
  • 最頻値

グループ化

同じキー値を持つデータをリストアップするには、まずEnum.group_by()で「キー値」と「データリスト」という形式でグルーピングし、キー値とデータリストの各々に列名を付け直す操作をします

lib/sample_db_web/templates/page/index.html.eex

datas = result
  |> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) ) 
  |> Enum.map( &( 
    %{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 ) |> Lst.to_csv } ) )

カウント

カウントは、グルーピング後のキー値とデータリストの各々に列名を付け直す際、データリストにEnum.count()することで取得できます

lib/sample_db_web/templates/page/index.html.eex

datas = result
  |> Enum.group_by( &( &1[ "Profession" ] ), &( &1[ "ApplicantIncome" ] ) ) 
  |> Enum.map( &( 
    %{ "Profession" => elem( &1, 0 ), "ApplicantIncome" => elem( &1, 1 ) |> Enum.count } ) )

合計

合計は、グルーピング後のキー値とデータリストの各々に列名を付け直す操作時、データリストをEnum.reduce()で足しこんでいけば取得できます

lib/sample_db_web/templates/page/index.html.eex

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()を行うことで取得できます

lib/sample_db_web/templates/page/index.html.eex

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 } ) )

lib/sample_db_web/templates/page/index.html.eex

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.「いいね」よろしくお願いします

よろしければ、ページ左上の image.pngimage.png のクリックをお願いしますー:bow:
ここの数字が増えると、書き手としては「ウケている」という感覚が得られ、連載を更に進化させていくモチベーションになりますので、もっとElixirネタを見たいというあなた、私たちと一緒に盛り上げてください!:tada:

10
2
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
10
2