Qlikのレイヤ表示で銭湯マップをつくってみる(その3)

こんにちは!Yokoです。
Qlikで作る東京23区 銭湯マップの第3回は、結構細かい作業になりそう…
マップ上のエリアをズームしたりせずに、検索機能でバシッと表示してほしい!
そんな気の利いたアプリにしたいものです。
気合入れて頑張りますっ!!

目次

検索機能の要件

マップは、駅の緯度・経度、銭湯の緯度・経度を基に表示されています。
検索するための要件を整理してみます。

  • 駅が選択された時には、駅の周辺の銭湯が表示される
  • 銭湯が選択された時は、銭湯の周辺の駅が表示される
  • 駅と銭湯が選択されたときには、駅と銭湯を含むエリアの周辺の駅と銭湯が表示される
  • 表示される周辺の駅や銭湯は距離を設定して表示エリアを可変にしておきたい

特に4つめの「距離を設定して表示エリアを可変に」というのが厄介な気がします。
距離を測定するにしても、銭湯と駅の組み合わせはたくさんあるし、緯度・経度から2地点間の距離を求めるのはとても複雑です。
そこで僕が考えたのは、絞り込まれた駅や銭湯の緯度・経度の最大、最小の値から、緯度・経度を広げる値をパラメータ化すればよいのでは?ということでした。
とりあえず、この方針で進めて行くことにします。

変数の準備

まずは、緯度・経度の最大、最小の値から、緯度・経度を広げる値を変数として設定します。
値が大きくなれば、エリアが拡大されますが、正の値だと、ズームインするには値を小さくする必要があり、感覚的には逆のほうが望ましいと思うので、負の数で設定します。
定義は-0.03にしましたが、これがデフォルト値となります。

変数名定義
vDistance-0.03

次に緯度・経度のエリアを設定するために、4つの変数を作成していきます。考え方は以下のとおりです。
(vDistanceは負の値にしたので、符号は逆に設定します)

変数名論理式
vLat_Max緯度の最大 – vDistance
vLat_Min緯度の最小 + vDistance
vLon_Max経度の最大 – vDistance
vLon_Min経度の最小 + vDistance

上記の式を変数で定義していきます。

■ vLat_Max

=If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0 and Count({1} 銭湯ID)-GetPossibleCount(銭湯ID)>0,
	RangeMax(Max([駅_緯度]),Max([緯度])),
    If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0,
    	Max([駅_緯度]),Max([緯度])
    )
)
-$(vDistance)

式を解説しますね。

  • 1行目 If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0 and Count({1} 銭湯ID)-GetPossibleCount(銭湯ID)>0
    駅コードが絞り込まれている かつ 銭湯IDが絞り込まれているとき
  • 2行目 RangeMax(Max([駅_緯度]),Max([緯度]))
    駅_緯度と銭湯の緯度の最も大きい緯度を比較して、大きい方を取得(値を列記してMaxを取るときはRangeMaxだよ)
  • 3〜4行目
    駅コードが絞り込まれている時は、駅の緯度の最大を取り、そうでないときは銭湯の緯度の最大をとる
  • 7行目 -$(vDistance)
    vDistanceの分だけエリアを拡大する

残りの変数も同様に設定していきます。

■ vLat_Min

=If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0 and Count({1} 銭湯ID)-GetPossibleCount(銭湯ID)>0,
	RangeMin(Min([駅_緯度]),Min([緯度])),
    If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0,
    	Min([駅_緯度]),Min([緯度])
    )
)
+$(vDistance)

■vLon_Max

=If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0 and Count({1} 銭湯ID)-GetPossibleCount(銭湯ID)>0,
	RangeMax(Max([駅_経度]),Max([経度])),
    If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0,
    	Max([駅_経度]),Max([経度])
    )
)
-$(vDistance)

■vLon_Min

=If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0 and Count({1} 銭湯ID)-GetPossibleCount(銭湯ID)>0,
	RangeMin(Min([駅_経度]),Min([経度])),
    If(Count({1} 駅コード)-GetPossibleCount(駅コード)>0,
    	Min([駅_経度]),Min([経度])
    )
)
+$(vDistance)

以上で変数の設定は完了です。

関連フィルタ等の設定

シート上にフィルターパネル、スライダー、テーブルを追加していきます。完成形はこちらです。

■ フィルターパネル
駅関連のフィルタとして、「路線」と「駅名」、銭湯の「区」と「銭湯名」のフィルターパネルを設定します。
取り込んだ項目のままではなく、上で作成した変数に基づき、条件に合致するもののみ表示するように数式で定義していきます。
フィルタのラベルは下記の各項目の名称を指定して下さい。

【路線名】

=Aggr(Only({$<駅_緯度={">=$(vLat_Min)<=$(vLat_Max)"},駅_経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [路線名]),[路線名])

【駅名】

=Aggr(Only({$<駅_緯度={">=$(vLat_Min)<=$(vLat_Max)"},駅_経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [駅名]),[駅名])

【区】

=Aggr(Only({$<緯度={">=$(vLat_Min)<=$(vLat_Max)"},経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [区]),[区])

【銭湯名】

=Aggr(Only({$<緯度={">=$(vLat_Min)<=$(vLat_Max)"},経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [銭湯名]),[銭湯名])

■ スライダー
スライダーは、カスタムオブジェクト > Qlik Dashboard bundle > Variable inputをフィルタの右横に配置し、以下のように設定します。
Min, Max, Stepは表示を確認してから再設定でいいと思います。

設定項目設定
Variable > NamevDistance
Variable > Show asSlider
Value > Min-0.01
Value > Max-0.05
Value > Step0.001

■ ストレートテーブル
選択された銭湯の住所を確認できようにストレートテーブルを追加します。
銭湯IDは以下の数式を設定し、エリアの絞り込みに対応するようにします。「NULL値を含める」のチェックを外すのを忘れないで下さい。

=Aggr(Only({$<緯度={">=$(vLat_Min)<=$(vLat_Max)"},経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [銭湯ID]),[銭湯ID])

マップの設定

ストレートテーブルを作成していて気付いたことなのですが、同じ銭湯名が複数あって、これはマップ表示上は弊害になるはずです。「松の湯」だけで都内には5箇所もあります。
また、駅名に関しても、新宿のように複数の路線が乗り入れている場合、異なる緯度・経度を持っているようです。
それを考えると、マップ上のポイントは「駅名」や「銭湯名」ではなく、「駅コード」、「銭湯ID」を設定すべきですね。これに対応する形でマップの設定に変更を加えていきます。

■ 駅のポイントレイヤー
駅は「駅コード」を持っていますので、駅コードでポイントするようにします。その際、フィルターなどで絞り込んだ範囲を表示するように以下のように設定します。タイトルは「駅コード」で設定します。

=Aggr(Only({$<駅_緯度={">=$(vLat_Min)<=$(vLat_Max)"},駅_経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [駅コード]),[駅コード])

また、マップ上のラベルの表示は駅名にしたいので、オプションのラベルは「駅名」に設定しておく必要があります。
さらに、マウスホバーした時に「駅名」と「路線」を表示したいのでツールヒントも設定しておきます。
ツールヒントではカスタムにして「基本的な行を非表示にする」にチェックを入れ、メジャーを2つ追加します。
万一、同じ地点で複数の路線がある場合を想定してConcatで結合して表示するようにします。

メジャー定義
=Concat(Distinct 駅名,’+’)
路線=Concat(Distinct 路線,’+’)

■ 銭湯のポイントレイヤー
銭湯は「銭湯ID」を持っていますので、銭湯IDでポイントするようにします。エリア絞り込みの対応は駅同様に以下のように数式を定義します。

=Aggr(Only({$<緯度={">=$(vLat_Min)<=$(vLat_Max)"},経度={">=$(vLon_Min)<=$(vLon_Max)"}>} [銭湯ID]),[銭湯ID])

マップ上のラベルも「銭湯名」で設定します。
ツールヒントも以下のように設定します。駅と違い、同じ地点に複数の銭湯はない想定です。

メジャー定義
銭湯=Only(銭湯名)
住所=Only(住所)

動作確認

マップの設定も完了したので、動作確認を行ってみます。
まず、デフォルト表示から路線=「東京メトロ丸の内線」を選んでみます。丸ノ内線沿線の駅がプロットされ、さらにその周辺エリアの銭湯が表示されました。
まずは第一関門クリアです。

次に新宿駅をフィルターから選択してみます。そうしますと、新宿駅近辺の銭湯が表示されました。
スライダーを動かし、ズームイン・ズームアウトしてみると、周辺エリアが拡大したり、縮小されたりして、表示される銭湯も変わります。

さらに銭湯を絞り込んでみます。
一旦、路線や駅の選択をクリアし、「銭湯名」のフィルターから「松の湯」を選んでみます。松の湯が5箇所表示されました。松の湯周辺の駅も表示されていますが、たくさんありすぎて埋もれています😂

「区」のフィルターで新宿区を選択して1つの銭湯に絞り込むと、最寄り駅と銭湯の位置関係がわかります。ここでは中井駅と東中野駅が同じくらいですかね。東中野はJRと大江戸線が離れているので、ちゃんと2つ表示されています。

大江戸線の東中野駅を選択しますと、東中野駅と松の湯のルートを確認するためのマップ表示になりました。
ここまで来ましたら、マウスでさらにズームしたり上下左右に移動したりしながら詳細を確認できます。
これで、できたっぽい😁
マップ上で投げ縄選択もできるようで、なかなかいい感じです。

まとめ

いやーー疲れました😩
結構、面倒な設定が多かったっす。
二度とやりたくない!
とは言いません。お客さんに頼まれたらやりまする。

ところで、何気なくAggr(Only…)を使ってましたが、軸やフィルターの数式で、If文を使う人っていますよね。
If文使っちゃいけないわけではありませんが、選択状態の表示に数式が出てしまいますので、Aggr(Only()…)を使うべし!
僕は「SET文で書けるところでは、極力If文は使わないように!」と教えています。実は結果が異なったりすることもあるんですよ。脅しじゃなくてさ。

てなわけで、「電車で行く東京23区銭湯マップ」シリーズは完了です。
続編はありません、多分…
ではまた!

関連記事はこちら
Qlikのレイヤ表示で銭湯マップをつくってみる(その1)
Qlikのレイヤ表示で銭湯マップをつくってみる(その2)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次