見出し画像

【テキスト×GPS】あなたが昨日見逃した”美味しいお店”をリストアップするプログラムを作った!


お疲れ様です。東京で仕事をしているものです。へちやぼらけと申します。(統計学・機械学習に関する動画も投稿している、所謂YouTuberです。笑)

ポケモンGO・ドラクエウォークのブームなどを目の当たりにしてると、「GPSを使った地理情報連動型アプリって、今後流行るんじゃね?」と密かに思ってます。また、Zenlyっていう「友達と位置情報を共有するSNSアプリ」もあったりするんですよね。

と、言うことで今回はテキストマイニング×GPS(地理データ)です。GPS情報から昨日あなたが歩いた場所を取得して、あなたが見逃した”美味しいお店”をリストアップするプログラムを作ります。

リストアップの際は、口コミの情報をネガポジ分析し、より良い口コミが含まれているお店を見つけます!

ちなみに、位置情報からお店を取得する際は”ぐるなびAPI”を利用させていただきました。

〇アルゴリズム概要

ざっくりとアルゴリズムの概要ですが、とってもシンプル。以下の5つのステップで”美味しいお店”をリストアップします。

⓪スマホのGPSをON!位置情報をGoogleのサーバーに送る。
①自分の位置情報を取得!
②取得した位置情報をPythonに読み込ませる。
③リスト形式で格納した位置データを”ぐるなびAPI”に投げる。
④投げたあとに返ってくる「周辺のお店情報」「そのお店の評価」「口コミ」をリストに格納する。
⑤取得したお店の中で評価4.5以上のお店をピックアップ。更に、ピックアップしたお店の口コミをネガポジ分析!良い口コミを持つお店をリストアップ。

こんな感じです。以下ステップごとに確認をしていきましょう!

⓪スマホのGPSをON!位置情報を送る。

アンドロイド端末の場合「Googleアカウントがログインした状態」「ロケーション履歴がオン」「デバイスの現在地送信機能がオン」の3つの状態を満たす場合に限り、あなたの位置情報が保存されるようです。

①自分の位置情報を取得

保存した位置情報はグーグルマップから取得可能だ。取得方法は、個人のプライバシーに関わるため詳細には触れない。自分で調べて自分の責任下で実施して下さい

ちなみに、自分はGoolgemapsのページからロケーション履歴を取得しています。取得したロケーション履歴は↓。緯度・経度及び、その時の自国がjson形式で保存されているぞ。

画像1

②位置情報をPythonに読み込ませる

取得した”ロケーション履歴.json”をPythonに読み込ませます!と言っても、単純にjsonファイルを読み込むだけです。

jsonのlocationに位置情報があるので、それを変数locationsに格納します。

with open("ロケーション履歴.json") as file:
   data = json.load(file)

# locationsから履歴情報を取得
locations = data["locations"]

locationsには、あなたが通った場所が緯度・経度として保存されています。さて、locaionsの緯度・経度を取得してマップ上に表示してみよう!コードは↓。

# locationsの情報をitemに代入
for item in locations:
   # itemから緯度経度を取得!
   timestamp = datetime.fromtimestamp(int(item["timestampMs"]) / 1000)
   lat = convert_lat_lng(item["latitudeE7"])
   lng = convert_lat_lng(item["longitudeE7"])
   accuracy = item["accuracy"]
・
・
・

map.fit_bounds(positions)
map

表示したマップはこんな感じ↓。俺が東京をふらふらしたとある1日です。

画像2

③位置データを”ぐるなびAPI”に投げる。

ぐるなびAPIに先ほどの緯度・経度をぶん投げます。投げると、「その周辺のお店の情報」「お店の評価」「お店の口コミ」が返ってくるので、変数shop_dicに格納します。

Url = "https://api.gnavi.co.jp/PhotoSearchAPI/v3/"
shop_dic = pd.DataFrame()
#パラメタ
for tate, yoko in positions:
   params={}
   params["keyid"] = "?????????????????????" #取得したアクセスキー
   params["latitude"] = float(tate)
   params["longitude"] = float(yoko)
   params["range"] = 3 #1:300m、2:500m、3:1000m、4:2000m、5:3000m
   params["hit_per_page"] =50
   #リクエスト結果
   shop_dic = shop_dic.append(requests.get(Url, params).json(),ignore_index=True)
   time.sleep(1)

④返ってきた値の整形

ぐるなびAPIから受け取った情報はjsonファイルで返ってきます。情報量が多く扱いにくい。なので、shop_dicから「お店id」「店名」「評価」「口コミ」のみを抽出して、それを変数shopsに格納します。

ちなみに、この処理は例外処理が多く、思ったよりごちゃごちゃになってしまった・・。コードは肝となる部分だけ載せます。↓です。

if (get[str(i)]["photo"]["shop_name"] != get[str(i+1)]["photo"]["shop_name"]):
      try:
          rank = float(get[str(i)]["photo"]["total_score"])
      except KeyError as e:
          rank = 3.0
          
      temp_s   = pd.DataFrame([[get[str(i)]["photo"]["shop_id"],
                                get[str(i)]["photo"]["shop_name"],
                               (temp_rank + rank)/times,
                                temp_kome + get[str(i)]["photo"]["comment"] + "。"]])       
      shops = shops.append(temp_s)

画像4


⑤いいお店をピックアップ!

はい、ということで、shopsの中からいいお店だけをピックアップします。ここら辺、センスの別れるところだと思いますが、私はまず「評価が4.3以下のお店」を全部捨てることにしました。

#平均評価が、4.3点以下は捨てる。
shops_sel = shops_sel[shops_sel[2]>4.3]

次はその中から、より良いお店を”口コミ”から決めます。

下のコードは、実際に口コミをネガポジ分析している部分。辞書は有志の方が作られた「nega_poji.dic」を使います!(http://www.lr.pi.titech.ac.jp/~takamura/pndic_en.html)

# pn_ja.dicファイルから、単語をキー、極性値を値とする辞書を得る
def load_pn_dict():
   dic = {}
   
   with codecs.open('nega_poji.dic', 'r', 'UTF-8') as f:
       lines = f.readlines()
       
       for line in lines:
           # 各行は"良い:よい:形容詞:0.999995"
           columns = line.split(':')
           dic[columns[0]] = float(columns[3])
           
   return dic
for i,texts in enumerate(shops_sel.iloc[:][3]):
   # CorpusElementのリスト
   naive_corpus = []
   naive_tokenizer = Tokenizer()
   tokens = naive_tokenizer.tokenize(texts)
   element = CorpusElement(texts, tokens)
   naive_corpus.append(element)   

   # 感情極性対応表のロード
   pn_dic = load_pn_dict()
   # 各文章の極性値リストを得る
   for element in naive_corpus:
       element.pn_scores = get_pn_scores(element.tokens, pn_dic)
   print(sum(element.pn_scores))
   shops_sel.iloc[i,4] = sum(element.pn_scores)

出力結果は以下の様な感じ。評価が4.3以上でかつ、口コミの良かったお店がリストアップされます!新しく追加した5列目(4の列目)がネガポジの結果です。

画像4

この記事が気に入ったらサポートをしてみませんか?