Edited at

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

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

昨日は、@kobatako さんの「GraphQL for Elixir#3 Middlewareと認証について考える」でした


fukuoka.ex代表のpiacereです

今回もご覧いただいて、ありがとうございます:bow:

この連載の、前回までの記事は、以下になります

 |> 関数型でデータサイエンス#1:様々なデータをインプットする

 |> 関数型でデータサイエンス#2:インプットしたデータを変換する

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

今回は、前回の前半に続き、「インプットしたデータの集約」の後半を解説します

ElixirのEnumが、平均値・中央値などの「統計」機能を標準で計算できないため、ここを対応していきます

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




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

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

image.png


データ集約(続き)

以下について、説明します


  • 平均値

  • 中央値

  • パーセンタイル

  • 分散値

  • 標準偏差

  • 最頻値


統計ライブラリ「Statistics」のインストール

統計ライブラリを自作しようかな、と思ったら、「Statistics」という統計ライブラリを発見したので、こちらをインストールして、利用します

mix.exsの「def deps do」配下に追記します(:phoenix~の記載の上行に追加)

ついでに、小粒でピリリなユーティリティライブラリ「smallex」のバージョンアップもしておきます


mix.exs

defmodule SampleAnalytics.Mixfile do

use Mix.Project

defp deps do
[
{:statistics, "~> 0.5.1"},
{:smallex, "~> 0.1.8"},
{:phoenix, "~> 1.3.0"},

]
end


ライブラリを取得します(要ネット接続)

mix deps.get

Phoenixサーバーを起動することで、コンパイルします

iex -S mix phx.server


平均値

平均値は、データリストにStatistics.mean()を行うことで取得できます


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 ) |> Statistics.mean } ) )



中央値

中央値は、データリストにStatistics.median()を行うことで取得できます


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 ) |> Statistics.median } ) )



パーセンタイル

パーセンタイルは、データリストにStatistics.percentile()を行うことで取得できます

たとえば、90%tileであれば、以下の通りです


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 ) |> Statistics.percentile( 90 ) } ) )



分散値

分散値は、データリストにStatistics.variance()を行うことで取得できます


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 ) |> Statistics.variance } ) )



標準偏差

標準偏差は、データリストにStatistics.stdev()を行うことで取得できます


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 ) |> Statistics.stdev } ) )



最頻値

最頻値は、データリストにStatistics.mode()を行うことで取得できます


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 ) |> Statistics.mode } ) )



終わり

今回は、「インプットしたデータの集約」のうち、統計を伴う集計を行いました

統計ライブラリ「Statistics」のおかげで、だいぶラクができた感じですね

「Statistics」には、上記以外にも、相関係数を取得するStatistics.correlation()や、調和平均を取得するStatistics.harmonic_mean()、尖度を取得するStatistics.kurtosis()、歪度を取得するStatistics.skew()、

Zスコアを取得するStatistics.zscore()など、便利な統計関数が揃っているので、トレーディングなどのデータサイエンス以外の分野でも活用できそうです

次回は、「インプットしたデータの変形」を行います

明日は @yukq16 さんの「Elixirで関数の実行速度を測定する」です


p.s.「いいね」よろしくお願いします

よろしければ、ページ左上の image.pngimage.png のクリックをお願いしますー:bow:

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