概要
Google Mapのレビュー点数が高いレストランが集まるエリアってどこなんだろ?と疑問に思い、ヒートマップにしてみました
レビューのレーティングを取ってくる
Place Search APIを使います。このWrapperを使わせて頂きました
- 単純にレストランの位置×レビューをプロットするとレストランが多い地域が赤いヒートマップになるだけなので、エリアをグリッド状に分割して、各グリッド内のレストランの平均レーティングで重み付けする想定で行きます
- 今回グリッドは約500m刻みになるよう設定したので、
radius
を500とします - 結果は最大20件までなのでレストラン密集地域ではAPIお任せのランダムな20件の平均となります
fetch_rating.rb
@client = GooglePlaces::Client.new(API_KEY)
col_num.times do |c|
row_num.times do |r|
lng = south_west[:lng] + c * diff
lat = south_west[:lat] + r * diff
result = @client.spots(lat, lng, language: :ja, types: :restaurant, radius: 500)
# 平均出したりする処理...
end
end
料金について
- 東京都だけに絞っても、網羅的にやろうとすると2188km²/0.25km²=約8700requestが必要
- 料金は$13/1000reqぐらいになりそうなのでご利用は計画的に(今回取った範囲は無料クレジット内に収まりました)
ヒートマップを描画する
- KibanaやTableauをこの為に用意するのは面倒
- Google Data Studioなら無料かつ手軽にヒートマップ化できるが、ズームレベルが「国」までしか選べない(USなら州までいける)
- という事でMaps JavaScript APIのHeatmapLayerを使います
HeatmapLayer
- HeatmapLayerに渡すデータに
weight
を含ませると重み付けができる(weight: 3なら内部的に3つの点がプロットされる扱いとなる) - しかし線形に反映されるだけだとこんな感じにメリハリの無いヒートマップになってしまう
- なので適当に
weight = Math.pow(weight, 3)
とかして非線形にします
結果はこんな感じです。
西麻布、目黒近辺、あとなんか西の方が強いですね。
heatmap.js
fetch('summary.json')
.then(response => response.json())
.then(json => {
const heatmapData = json.map(d => {
const location = new google.maps.LatLng(d['location']['lat'], d['location']['lng'])
const weight = Math.max(0, Math.pow(d['avg'] - 3, 3))
return {location, weight}
})
const map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(35.672196, 139.729521),
zoom: 12.3,
maxZoom: 12.6,
minZoom: 12,
disableDefaultUI: true
})
const heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
radius: 40,
opacity: 0.5,
gradient: ['white', '#ffff99', '#fff000', '#ff0000'],
})
heatmap.setMap(map)
})