Tableauのランキング表示をAmazon RedshiftのRANKウインドウ関数で置き換える

2015.04.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Tableauには表計算関数というものが用意されており、ちょっとした便利機能が色々と利用出来るようになっています。ですが、Tableauだけで実現したい内容を対応しようとした際に良い解決策が浮かばなかったので一部を別の手法で置き換えて実現してみたよ、というのを最近行いました。当エントリではその内容をご紹介してみたいと思います。

目次

実現したい内容:TopN表示したデータのランキング表示を全件の中でのランク表示としたい

まずは以下の内容を御覧ください。日本プロ野球の2015年の打撃結果をデータ化してみたものです。打席に立った選手約200数十名のデータを全件表示させた際の内容を表示させています。

インデックス(データ内では[INDEX]):パーティション内の現在の行のインデックスを返します。下記データでは並び替えたデータのインデックスそのまま表示されています。

INDEX()

ランキング(データ内ではRANKING(項目名):指定した引数の項目のランキング順位を算出します。下記データでは安打及び打率のランキングを算出する計算フィールドをRANKING(安打)RANKING(打率)として用意し、利用しています。

RANKING([安打],'desc')
RANKING([打率],'desc')

この場合、DeNAの筒香選手は安打数4位、打率18位となっています。全200数十件中の順位です。

tableau-rank-01

問題点:Tableauのウインドウ関数は『現在のデータ』に対して値を算出してしまう

一方、TopN件表示させた場合の表示について見てみます。選手名を元にしてTopNのフィルタを作成し、

tableau-rank-02

その流れでパラメータも作成します。TopNフィルタは『安打数』が指標になっています。

tableau-rank-03

TopNフィルタを使って、安打数の上位10件を出してみます。安打数は4位のままですが、打率もなぜか4位になってしまっています。

tableau-rank-04

これはTableauのランキング関数が、表示されている現在のデータに対して実行されてしまっているからです。この場合、安打数のTopN表示で絞りこまれた10件の中でのランキング算出されている形になると思われます。

パーティション内の現在の行に対して標準の競争ランクを返します。同一の値には同一のランクが割り当てられます。昇順または降順を指定するには、オプションの 'asc' | 'desc' 因数を使用してください。既定では降順です。

対応策:Amazon Redshiftのウインドウ関数でTableauのランキングを置き換える

ではどうするか。ここでは、Amazon RedshiftのRANKウインドウ関数を用いて対象データのランキング値を出す事にして、Tableauでは算出を行わずにそのまま出すことにしました。以下はCSVのファイル内容例。

選手ID,チーム,選手名,打率,試合,打席数,打数,得点,安打,二塁打,三塁打,本塁打,塁打,打点,盗塁,盗塁刺,犠打,犠飛,四球,敬遠,死球,三振,併殺打,長打率,出塁
率
players_id,team,player_name,batting_average,game,plate_appearance,at_bats,points,single,double,triple,home_run,total bases,rbi,stolen_base,caught_stealing,sacrifice_bunt,sacrifice_fly,intentional_walk,unintentional_intentional_walk,hit_by_pitch ,swing_out,take_two,slugging_percentage,on_base_percentage
1,巨人,坂本 勇人,0.245,13,58,53,6,13,2,1,0,17,4,0,0,0,0,5,0,0,8,0,0.321,0.31
2,巨人,阿部 慎之助,0.298,13,53,47,4,14,2,0,0,16,4,0,0,0,2,4,0,0,11,0,0.34,0.34
3,巨人,村田 修一,0.178,13,52,45,4,8,0,0,0,8,2,1,0,1,0,5,0,1,10,4,0.178,0.275
4,巨人,亀井 善行,0.327,13,52,49,7,16,2,0,3,27,9,0,1,0,1,2,0,0,11,0,0.551,0.346
5,巨人,井端 弘和,0.238,13,49,42,4,10,0,0,0,10,2,1,1,1,0,5,0,1,3,2,0.238,0.333
6,巨人,長野 久義,0.2,13,41,35,3,7,1,0,0,8,5,0,0,0,0,6,0,0,8,1,0.229,0.317
7,巨人,高橋 由伸,0.167,11,37,30,2,5,0,0,0,5,3,1,0,0,0,6,0,1,6,0,0.167,0.324
8,巨人,片岡 治大,0.308,12,32,26,3,8,1,0,2,15,4,4,2,4,0,2,0,0,2,0,0.577,0.357
9,巨人,セペダ,0,12,20,16,1,0,0,0,0,0,0,0,0,0,0,4,0,0,4,1,0,0.2
10,巨人,金城 龍彦,0.313,9,17,16,2,5,0,0,0,5,2,0,0,0,0,1,0,0,1,0,0.313,0.353
11,巨人,松本 哲也,0.067,10,16,15,3,1,0,0,0,1,0,1,0,0,0,1,0,0,4,0,0.067,0.125
12,巨人,小林 誠司,0.125,6,11,8,0,1,0,0,0,1,0,0,0,1,0,2,0,0,1,0,0.125,0.3
13,巨人,相川 亮二,0.333,3,8,6,2,2,0,0,0,2,2,0,0,0,0,2,0,0,2,0,0.333,0.5
14,巨人,中井 大介,0.333,2,4,3,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0.333,0.5
15,巨人,鈴木 尚広,1,5,1,1,0,1,0,0,0,1,0,2,0,0,0,0,0,0,0,0,1,1
16,巨人,寺内 崇幸,0,4,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0
17,巨人,實松 一成,0,3,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1
18,巨人,橋本 到,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0
19,阪神,鳥谷 敬,0.28,12,57,50,4,14,2,0,0,16,0,2,0,0,0,7,1,0,6,1,0.32,0.368
20,阪神,上本 博紀,0.143,12,55,42,6,6,1,0,1,10,2,1,0,6,0,7,0,0,11,0,0.238,0.265
21,阪神,西岡 剛,0.319,12,53,47,5,15,4,0,1,22,6,1,1,0,0,5,0,1,6,1,0.468,0.396
22,阪神,ゴメス,0.244,12,52,45,5,11,4,0,1,18,6,0,1,0,0,6,0,1,9,3,0.4,0.346
23,阪神,マートン,0.229,12,50,48,3,11,3,0,0,14,5,0,0,0,0,2,0,0,9,1,0.292,0.26
24,阪神,梅野 隆太郎,0.262,12,47,42,3,11,3,0,0,14,6,0,2,3,0,1,0,1,10,0,0.333,0.295
25,阪神,福留 孝介,0.212,11,44,33,6,7,1,0,2,14,5,1,0,0,0,11,0,0,5,0,0.424,0.409
26,阪神,大和,0.179,10,31,28,0,5,2,0,0,7,2,0,0,0,0,2,2,1,7,0,0.25,0.258
27,阪神,新井 良太,0.091,9,13,11,1,1,0,0,0,1,1,0,0,0,0,2,0,0,4,0,0.091,0.231
:

そして以下がテーブル作成例。

create-table.sql

DROP TABLE public.npb_record_2015;
CREATE TABLE public.npb_record_2015 (
  players_id INT NOT NULL,
  team VARCHAR(20) encode lzo NOT NULL,
  player_name VARCHAR(30) encode lzo NOT NULL,
  batting_average NUMERIC(4,3),
  games SMALLINT NOT NULL,
  plate_appearance  SMALLINT NOT NULL,
  at_bats SMALLINT NOT NULL,
  points SMALLINT NOT NULL,
  single SMALLINT NOT NULL,
  double SMALLINT NOT NULL,
  triple SMALLINT NOT NULL,
  home_run SMALLINT NOT NULL,
  total_bases SMALLINT NOT NULL,
  rbi SMALLINT NOT NULL,
  stolen_base SMALLINT NOT NULL,
  caught_stealing SMALLINT NOT NULL,
  sacrifice_bunt SMALLINT NOT NULL,
  sacrifice_fly SMALLINT NOT NULL,
  intentional_walk SMALLINT NOT NULL,
  unintentional_intentional_walk SMALLINT NOT NULL,
  hit_by_pitch SMALLINT NOT NULL,
  swing_out SMALLINT NOT NULL,
  take_two SMALLINT NOT NULL,
  slugging_percentage NUMERIC(4,3),
  on_base_percentage NUMERIC(4,3)
);

そして以下がランキングの算出例。項目別にそれぞれの全件におけるランキング値を算出しています。

SELECT
  public.npb_record_2015.players_id,
  public.npb_record_2015.team,
  public.npb_record_2015.player_name,

  public.npb_record_2015.batting_average,
  RANK() OVER( ORDER BY public.npb_record_2015.batting_average DESC) AS rank_of_batting_average,

  public.npb_record_2015.single,
  RANK() OVER( ORDER BY public.npb_record_2015.single DESC) AS rank_of_single,

  public.npb_record_2015.double,
  RANK() OVER( ORDER BY public.npb_record_2015.double DESC) AS rank_of_double,

  public.npb_record_2015.triple,
  RANK() OVER( ORDER BY public.npb_record_2015.triple DESC) AS rank_of_triple,

  public.npb_record_2015.home_run,
  RANK() OVER( ORDER BY public.npb_record_2015.home_run DESC) AS rank_of_homerun

FROM
  public.npb_record_2015;

以下が上記(Redshiftの)RANKウインドウ関数で算出されたデータをそのまま使ったTableauビューになります。全件表示での内容同様に、安打数のランキングが表示されている事が確認出来ました。Tableauでは関数を使う際にもTableau上で変換・算出の処理を行う事になりますので件数が膨れ上がるとパフォーマンス的にも無視出来ないコストになる可能性があります。その部分を予め計算しておく事でその部分のコストも削減出来るかも知れないですね。

tableau-rank-05

Tableau Public Contens

以下は今回の検証で用いたTableau Publicダッシュボードになります。実際に触れるので挙動を確かめてみてください。

まとめ

以上、Amazon RedshiftとTableauの合わせ技によるグラフ機能の実現方法に関するご紹介でした。『こんな内容を見たい』というゴールはユーザー側視点である訳なので、それをどの様にデータを変換させて、処理を経由させて見せる事が出来るか...と言うのは柔軟に対応させて行きたいところですね。こちらからは以上です。

その他参考情報: