こんにちは!Yokoです。
とあるお客様から
前年比でランキングを出したいんだけど、雑魚が入ってきて目障りだから一定の基準以上の顧客だけ表示するようにならないですか?
って相談を受けました。
「雑魚」っていう表現はもちろん使わなかったんですが😂
「雑魚」というのは僕が今日勝手に命名しただけですが、意味わかりますよね?
パレートの法則だと
「全売上の80%は、上位20%の優良顧客によって生み出されている」
とか
「全商品の売上の80%は、上位20%の主力商品がもたらしている」
なんて言われるけど、今回の主旨は「全体の売上の◯%を占めている顧客の上位◯位」を抽出するいうことに等しいなと感じたわけです。
で、面倒なのでGemini先生に聞いてみたのですが、Gemini先生も詳しいようで、勘違いも多くて、結局は「こうすればできるんじゃないの?」と教えたら以下のようなコメントをいただきました🤣

「最高のベストプラクティス」っていうのは怪しいけどね。
別に「最後に」にしなくてもいいのに、もう終わりにしてほしいというGemini先生の心情を察して、これ以上聞かないことにしました。
では、さっそく解説していきます。
雑魚問題とは
実は雑魚問題はもっと身近なところにも潜んでいます。
Qlikでは、軸で表示する件数などを制限する機能がありますので、それを使って説明しますね。
下記のように軸の制限を固定数=3と設定すると、3つ指定しているにも関わらず、4つの顧客が表示されます。
そして、折れ線が途切れ途切れに…

これはなぜ起きているかというと、軸である年月ごとのTOP3を表示しているからです。
こちらの意図としては、全期間でTOP3である顧客を表示したいだけなんですが、こういう制限の掛け方はできないんですよね。
でも、雑魚問題を解決できれば、きちんと「全期間のTOP3」をきちんと表示できます。
本稿のゴール
雑魚問題のソリューションを解説するために、今回はこんな仕様のチャートを作ってみます。
- 全体の売上の◯パーセントを占める顧客だけを抽出する
- その中からTOP◯位までを指定して表示する
- 上記の条件はシート上で任意に指定できるようにする
この仕様を満たすために、変数と数式を駆使して実現していきます。
ロードスクリプトで事前に集計するなどの小細工は一切なしです。
事前準備
まず、変数を定義して、シート上に、変数に対応した「変数入力」のオブジェクトを配置します。
売上の累積構成比(パレート)はスライダー、ランキングの件数はドロップダウンで指定できるようにします。
| 変数名 | 定義 | 補足 |
|---|---|---|
| vPareto | 80 | %指定(80の場合は売上の80%を占めるの意) |
| vRank | 10 | ランキングを何位まで表示するか |
| vFractileCut | =Fractile(TOTAL Aggr(Sum({<売上日={“>=$(vMinDate)<=$(vMaxDate)”}>} 売上金額), 顧客名), (100-$(vPareto))/100) | 指定された期間の売上で、vParetoで指定されたフラクタイル (分位値) を求める |
vFractileCutの数式ですが、累積構成比で80%を指定した時は、0.2となるようにしています。
(フラクタル(分位)は小さいほうから計算するため、大小は逆になります)

アプローチ方法
今回のチャートでは、メジャー側の基本的な数式は期間を指定するSET文が入っています。
Sum({<[売上日]={">=$(vMinDate)<=$(vMaxDate)"}>} [売上金額])
このようなSET文の数式に条件を追加していく時に、まず考えるのは、顧客=P()などを使って、顧客自体を絞り込むことでしょう。
そうするとこんなP()関数の指定になりそうですね。
[顧客名] = P({< [顧客名] = {"=Sum({<[売上日]={'>=$(vMinDate)<=$(vMaxDate)'}>} [売上金額]) >= $(vFractileCut)"} >})
=Sum({<[売上日]={‘>=$(vMinDate)<=$(vMaxDate)’}>} [売上金額])と指定しないと、全期間の売上で計算してしまうことになり、正しい結果が得られません。
しかし、SET文の中にSETを入れる、さらにAggr()関数を入れるなど複雑なネスト構造にしてしまうとQlikがエラーを返してしまいます。
このエラー、Qlik中級以上の方は、よく遭遇すると思います(僕も何度も遭遇しています)。
僕はこういう時、メジャーでできなければ、軸で数式を使っちゃえと頭を切り替えるようにしています。
なるべく使わないようにしているIf条件式をこっそり忍ばせて…
軸の数式で絞り込む
はい、では軸の数式を設定しますね。
=Aggr(
If(Sum({<[売上日]={">=$(vMinDate)<=$(vMaxDate)"}>} [売上金額]) >= $(vFractileCut)
and Rank(Sum({<[売上日]={">=$(vMinDate)<=$(vMaxDate)"}>} [売上金額]),4) <= $(vRank)
,[顧客名])
,[顧客名])
上記の数式では以下のようなIf条件式で顧客を絞り込んでいます。
- 指定期間の売上がvFractile(デフォルトでは80%→0.2)以上
- 指定期間の売上のランクがvRank(デフォルトでは10)以下
- 上記の条件を満たす顧客
軸では、If文だけで終わると不用意な軸の選択になることがあるので、Aggr(数式, 顧客名)という構文にしておきます。
そして大事なことですが、If条件式を指定した場合、条件に合致しないものはNULLで返ってくるので、軸の「NULL値を含める」のチェックを必ず外すようにして下さい。
メジャーの数式はこちらです。シンプル!
Sum({<[売上日]={">=$(vMinDate)<=$(vMaxDate)"}>} [売上金額])
チャートタイトルには以下の数式を設定しておきました。
これで、売上がいくら以上の顧客が抽出されているかがユーザにもわかります。
='基準金額:$(=Num(Round($(vFractileCut)),'#,##0'))'
動作確認
ストレートテーブルが完成しました。
まずはデフォルトの状態(累積構成比=80%, Top10)はこのようになります。
雑魚は表示されません。

累積構成比を100%, Top20表示にすると雑魚が表示されるようになりました。

この方法を使えば、お客様からのご要望である「前年比TOP10(雑魚なし)」はできそうですね。
やってみれば、実は簡単😄
応用編:折れ線チャートの雑魚問題の解決
ストレートテーブルで、パレート指定によるランキング表示を実現してみましたが、冒頭で取り上げた折れ線チャートの問題もこの方法で解決できます。
ストレートテーブルを折れ線チャートに変換して年月を追加し、累積構成比=80%, Top3で表示してみます。
きちんと期間全体のTop3だけが表示されるようになりました。

Top20にしても累積構成比を50%にすると5社しか出てこないですね。売上の半分はこの5社で占められていることがわかります。

まとめ
パレート分析といえば、パレート図を思い浮かべますよね。
僕は「チャートで傾向がつかめたら、利用されないチャートの典型」みたいな言い方をしてきました。
「あーこうなってるんだ」って最初は見てもらえても、次第に見る人がいなくなって、「このシート非表示でいいんじゃない?」ってことになる悲しいチャートでした。
が、今回ご紹介したような「パレート指定して顧客のランキングのアップダウンを見ていく」って結構良さそうですよね。
最後にまとめますと、
- メジャー数式で行き詰まったら、軸の数式で実現できないか考えてみる
- 累積構成比はFractile関数を使えば一発で計算できる
ということで、今回はおしまいです。
では、また!


