Retty Tech Blog

実名口コミグルメサービスRettyのエンジニアによるTech Blogです。プロダクト開発にまつわるナレッジをアウトプットして、世の中がHappyになっていくようなコンテンツを発信します。

あなたのエリアは何処から? ~地理空間クラスタリングとの差分検証~

この記事はRettyアドベントカレンダー6日目の記事です。
昨日はkuwaharaさんの 「WebAssemblyのどこが良いのかわからないからこそWasmに触れてみた話」 でした。

はじめに

はじめまして、アナリストチームの渡邉と申します。

早速ですが、他人に目的地の位置を伝えるとき、あなたならどのように伝えますか?
伝え方に正攻法はありますか?誰に対しても同様に伝えられるでしょうか?

実はとても難しい位置の判断について、人と機械の判断に対して検証します。


ことの発端

Rettyはユーザーさんに合った飲食店が探せるサービスを提供しています。
飲食店さんの位置を適切に把握し、メタデータを付与し、検索し易さを向上することもサービス課題の一つです。

そして飲食店と同じく、弊社のオフィスビルの場所を紹介するのも、大きな課題の一つです。
今回はこの弊社オフィスビルの「一体どこのエリアで紹介すれば良いか」問題に終止符をうちたいと思います。

いざ検証!

「人間的な感覚」の調査

弊社のDBには営業中のお店だけで80万件超のお店が登録されています。
今回はそこから「人間的な感覚」でラベルづけされたエリアを確認します。

import folium
import pandas as pd

df = pd.read_csv(PATH)
df_area_azabujuban = df.query("area_name == '麻布十番'")
df_area_tamachi = df.query("area_name == '田町'")

今回は地図プロットのためにJavascript製のLeafletのラッパーライブラリ folium を活用します。 以降、 赤色のマーカーは弊社の位置を意味します。

まずは「麻布十番」について可視化してみましょう。

map_area_azabujuban = folium.Map([35.653968, 139.741666], zoom_start=15)
for i, r in df_area_azabujuban.head(500).iterrows():
  folium.Marker(location=[r['lat'], r['lng']], popup=r['name']).add_to(map_area_azabujuban)

  folium.Marker(
    location = [35.653968, 139.741666],
    popup='弊社',
    icon=folium.Icon(color="red")
).add_to(map_area_azabujuban)

map_area_azabujuban

麻布十番」のエリアだと判断されたお店プロット

結果から言うと、中心地ではないですが麻布十番と言えなくもないです。うーん…

次に「田町」について可視化してみましょう。

map_area_tamachi = folium.Map([35.653968, 139.741666], zoom_start=15)
for i, r in df_area_tamachi.head(500).iterrows():
  folium.Marker(location=[r['lat'], r['lng']], popup=r['name']).add_to(map_area_tamachi)

  folium.Marker(
    location = [35.653968, 139.741666],
    popup='弊社',
    icon=folium.Icon(color="red")
).add_to(map_area_tamachi)

map_area_tamachi

「田町」のエリアだと判断されたお店プロット

弊社とお店のマーカーが被っていますね。これは弊社オフィスビルの1階にあるカフェが「田町」とラベル付けされているからです。田町エリアのマーカー密集地から離れているため断定できませんが、この結果から人の判断では「田町」だと一旦は仮定します。

機械的な推測」の調査

それでは今回のメイン。地理空間クラスタリングを用いた分類を試してみます。今回は緯度経度データだけを用いてクラスタリングを行います。
また外れ値のような弊社オフィスでも分類されるように 簡単にK-means法を試します。

# library import
import numpy as np
from sklearn.cluster import KMeans

# preprocessing
df_which = df.query('area_name == ["麻布十番", "田町"]')
heisha = pd.DataFrame(
    pd.Series(
        ['00000000000','弊社','a','a','a',35.653968, 139.741666,'a'], index=df_which.columns, name='X'
        )
    ).T

df_which = pd.concat([df_which, heisha])
arr_which = df_which[['lat','lng']].values

# clustering
pred = KMeans(n_clusters=2).fit_predict(arr_which)
df_which['cluster_id']=pred

# plotting
df_which['cluster_id']=pred
df_which['cluster_color'] = df_which['cluster_id'].apply(lambda x: 'blue' if x==1 else 'red')

青=麻布十番、赤=田町

プロットされた結果をみる限り、青色のマーカーと言うことは「麻布十番」のエリアだと推測されました。

考察

簡潔な考察

おわりに

弊社のオフィスビルは、 住友不動産麻布十番」ビル と言える後ろ盾ができました。
また緯度経度情報の変換やクラスタリングの手法には、より適切なものは多々あると思いますが、今回はこの結果にて終わらせていただきます。 ご覧いただきありがとうございました。