さだまさしの歌詞に登場する地名をヒートマップに起こしてみた

# はじめに

さだまさし氏（まっさん）の歌には、特定の地域・場所を取り上げた歌が数多くあります。

* 昨日・京・奈良、飛鳥・明後日。
* 飛梅
* 長崎小夜曲

どれも素敵な歌ですね(^o^)
特に飛梅は、太宰府天満宮に行くたびに脳内再生されジーンときてしまう超名曲です。

これらを含むまっさんの歌には、どの地域が多く取り上げられているんだろう？
やっぱり長崎？東京？それとも...？の謎を解き明かすべく、キーボードを手に取りコードを書いてみました。

ちなみに「北の国から」は超有名どころですが、これまでのアドベントカレンダーにて何度もフィーチャーされている通り歌詞がないので、今回は調査対象外です。

# やったこと（ざっくり）

* まっさんの歌詞を品詞分解
* 地域名を抽出してジオコーディング
* 登場回数と座標をもとにヒートマップを生成

# やったこと（詳細）

## まっさんの歌詞を品詞分解

### 歌詞取得

歌詞サイトのスクレイピングを行いました。著作権の問題があるので、ここでは記載しません。

### 品詞分解

品詞分解には Python の形態素解析ライブラリ [janome](http://mocobeta.github.io/janome/) を使用しました。

```py3:tokenize_sample.py
#!/usr/bin/env python
# -* encoding: utf-8 -*

from janome.tokenizer import Tokenizer


def main():
	for token in Tokenizer().tokenize('心字池にかかる三つの赤い橋'):
		print(token)


if __name__ == '__main__':
	main()
```

上記のようなコードを書いて実行すると...

```csv
心字池	名詞,一般,*,*,*,*,心字池,シンジイケ,シンジイケ
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
かかる	動詞,自立,*,*,五段・ラ行,基本形,かかる,カカル,カカル
三つ	名詞,一般,*,*,*,*,三つ,ミッツ,ミッツ
の	助詞,格助詞,一般,*,*,*,の,ノ,ノ
赤い	形容詞,自立,*,*,形容詞・アウオ段,基本形,赤い,アカイ,アカイ
橋	名詞,一般,*,*,*,*,橋,ハシ,ハシ
```

おぉぉ！心字池がきちんと認識されている！！
と、テンションが上がります。

janome の詳細な仕組みや歴史については、中の方のスライド『[Pyconjp2015 - Python で作って学ぶ形態素解析](http://www.slideshare.net/tomokouchida505/pyconjp2015-python)』がありますのでご参照ください。（2015年生まれなんですね！ありがたや！）

## 地域名を抽出してジオコーディング

### 地域を抽出

あらかじめスクレイピングしておいた歌詞群を janome で解析し「地域」に該当する単語を拾い出します。
また、単語の登場回数をヒートマップの濃度に反映させようと思いますので、同時に単語のカウントも取りました。

```py3
def count_place():
	place_count_dict = {}
	with open('sada_lyrics.csv','r') as lyrics:
		reader = csv.reader(lyrics)
		for row in reader:
			t = Tokenizer(udic='sada_dict.csv', udic_enc='utf8')
			for token in t.tokenize(row[1]):
				if '名詞,固有名詞,地域' in token.part_of_speech:
					place_name = token.surface
					if place_name in place_count_dict:
						place_count_dict[place_name] = place_count_dict[place_name]+1
					else:
						place_count_dict[place_name] = 1
	return place_count_dict

```

カスタム辞書の読み込みも可能です。
[janome ドキュメント](http://mocobeta.github.io/janome/#id7)によると、辞書フォーマットは Mecab と一緒だそうです。

```csv:sada_dict.csv
湯島聖堂,1288,1288,5000,名詞,固有名詞,一般,*,*,*,湯島聖堂,ユシマセイドウ,ユシマセイドウ
スカイツリー,1288,1288,5001,名詞,固有名詞,一般,*,*,*,スカイツリー,スカイツリー,スカイツリー
```

janome ドキュメントの例には『東京スカイツリー』とありますが、皆さんご存知の「かすてぃら」では『スカイツリー』と歌われていますので、『スカイツリー』での登録推奨です。

#### （おことわり）

本当は固有名詞の地点を特定した結果もヒートマップに反映させたかったのですが、時間の都合で断念しました。
なので、辞書も使ってないです。話題に挙げておきながら、ごめんなさい。

### ジオコーディング

ジオコーディングには、これまた Python の [googlemaps](https://pypi.python.org/pypi/googlemaps) ライブラリを使用しました。

Google Maps API を利用することになるので、API キーの指定が必要です。
取得方法は [googlemaps の GitHub](https://github.com/googlemaps/google-maps-services-python) に記載されています。

```py3
import googlemaps

def geocode(place_name):
	gmaps = googlemaps.Client(key='write your API key')
	geocode_result = gmaps.geocode(place_name)
	coord = geocode_result[0]['geometry']['viewport']['northeast']
	return coord['lat'], coord['lng']
```

## ここまでまとめ

以下は、ここまでの作業（歌詞を品詞分解〜地域名を抽出〜ジオコーディング）を繋げたコードです。

```py3:sada_place_geocoder.py
#!/usr/bin/env python
# -* encoding: utf-8 -*

from janome.tokenizer import Tokenizer
import csv
import googlemaps


def main():
	writer = csv.writer(open('sada_places.csv','w'), delimiter=',')
	place_count_dict = count_place()
	gmaps = googlemaps.Client(key='write your API key')
	for place_name, place_count in place_count_dict.items():
		lat, lon = geocode(gmaps, place_name)
		writer.writerow([place_name, place_count, lat, lon])


def count_place():
	place_count_dict = {}
	with open('sada_lyrics.csv','r') as lyrics:
		reader = csv.reader(lyrics)
		for row in reader:
			t = Tokenizer()
			for token in t.tokenize(row[1]):
				if '名詞,固有名詞,地域' in token.part_of_speech:
					place_name = token.surface
					if place_name in place_count_dict:
						place_count_dict[place_name] = place_count_dict[place_name]+1
					else:
						place_count_dict[place_name] = 1
	return place_count_dict


def geocode(gmaps, place_name):
	geocode_result = gmaps.geocode(place_name)
	coord = geocode_result[0]['geometry']['viewport']['northeast']
	return coord['lat'], coord['lng']


if __name__ == '__main__':
	main()
```

結果として、地域名・歌詞上の登場回数・緯度・経度が出力されます。
カスタム辞書使っていないこともあり、ゴミレコードがちらほら見られますが今回は無視して進めます。

```csv:sada_places.csv
アメリカ,1,49.38,-66.94
バミューダ,1,14.5192371802915,121.0361231302915
秋田,1,39.86527460000001,140.5154199
春日山,1,37.1489639802915,138.2363259802915
ビクトリア,1,48.450518,-123.322346
御宮,1,36.4073904302915,136.4570957
水無瀬,1,34.8791869802915,135.6691649802915
京,3,30.5403905,120.3877692
春の,1,33.8689809,130.8083576
飛鳥,3,38.8972965,139.9375578
日,2,50.68819,5.675110099999999
鎌倉,2,35.3682478,139.5933376
風呂屋,1,34.93531738029149,135.7610285302915
山見,1,36.5698502,136.9701007
エルサレム,1,31.8829601,35.2652869
西の京,1,34.67190798029149,135.7844679802915
加,1,36.5431863,-6.255334599999999
ベルリン,1,52.6754542,13.7611176
喜楽,1,35.1904253,136.7319704
見附,3,37.5933274,139.0009869
ナガサキ,5,35.7377658,139.6976565
浦島,1,35.4839466,139.6447166
愛宕,1,35.9737504,139.6042941
嬉,1,34.4654479,135.5854033
秋篠,1,34.7155978,135.7837222
平安京,1,44.5883529,127.1930004
ホンコン,1,14.4904672802915,121.0242180302915
軽井沢,2,36.4240846,138.6571307
漢,2,32.555258,114.2922103
稲佐,1,32.7592694,129.8647033
京都,1,35.0542,135.8236
武蔵小金井,1,35.70241118029149,139.5080892802915
白萩,1,38.2529733,140.9109412
ちの,3,34.047811,-117.5995851
坂の下,1,35.3120498,139.5356368
ユーコン,1,69.646498,-123.8009179
宅間,1,34.0886418,132.9547384
南京,1,32.3940135,119.050169
フランス,3,51.0891658,9.5597934
実籾,1,35.6882069802915,140.0695889802915
迎,1,37.9205189,112.7839926
音金,1,37.2102144,139.9250478
藪,1,35.3875492,140.1588221
化野,1,35.2016331,135.4969237
海老名,1,35.4774536,139.4364727
れんげ,5,48.02912,8.027220699999999
マゼラン,1,31.8199301,76.95342
みちのく,1,35.5030142302915,139.6870448302915
真珠湾,1,21.3885713,-157.9335744
波止場,1,34.6863148,135.1933421
晴海,1,35.6634906,139.7897775
ニッポン,2,34.6687571,135.5100311
ソフィア,2,42.7877752,23.4569049
アラスカ,4,71.3868712,-129.9945562
揚子江,1,36.4361024802915,139.8532846302915
北前,1,26.3027021,127.7615069
津軽,1,35.0117177302915,135.7573022302915
銀座,1,35.6760255,139.7724941
露,1,51.2964846,22.6735312
合衆国,1,49.38,-66.94
カサブランカ,2,33.6486015,-7.4582757
東京,31,35.817813,139.910202
薬屋,1,35.0155830302915,135.7545184802915
極北,1,12.9797045,15.683687
仏蘭西,1,35.17525588029149,139.6558066802915
五条,1,39.5593820302915,115.7611693
バグダッド,2,33.4350586,44.5558261
観世音寺,1,33.5222913,130.5254343
赤坂,1,35.6782744,139.7459391
仏,4,34.9489952,136.9632495
ニューヨーク,1,40.91525559999999,-73.70027209999999
錦,1,32.2516958,130.9134777
チグリス,1,-15.4044999,-42.8735213
久方,1,35.10910000000001,136.9854947
波打,1,33.9145777,130.8043569
湯島,2,35.711327,139.7724702
平城山,1,34.71184798029149,135.8116589802915
甲子園,1,34.7234607,135.3633836
新宿,2,35.7298963,139.7451654
かすみ,1,24.0234098,82.02101979999999
富士,1,35.3539032,138.8118555
カレー,1,50.9818821,1.9320691
長崎,24,32.9686469,129.9938174
南山手,2,32.7361422,129.8708733
倶知安,1,43.015163,140.9243102
道地,1,36.1243706,139.5655411
坂元,1,37.9298369802915,140.9141139802915
四条,1,35.0044451802915,135.7580809302915
地中海,1,45.7927967,36.215244
あけぼの,1,26.2435843,127.6904124
神楽,1,34.6626033,135.1513682
安曇,2,36.3649943,137.8106765
ヒロシマ,1,31.9163645,131.4305945
峨眉山,1,29.7169085,103.6231299
横浜,1,35.5113,139.674
上野,1,36.1325774,138.8291853
チリ,6,-17.4983293,-66.4169643
用賀,1,35.62797998029149,139.6354899802915
キリマンジャロ,2,-3.0562826,37.3716347
揚羽,1,35.1848028,136.9673238
広島,6,34.4426,132.4865
ナイロビ,1,-1.164744,37.0493746
谷汲,1,35.5452879,136.6135764
練馬,2,35.779946,139.6811359
なんば,1,43.648665,-116.48121
浅草,1,35.7233639,139.8055923
押上,2,35.71155898029149,139.8137769802915
心斎橋,2,30.6801709802915,114.2062109802915
日本,9,45.5227719,145.8175503
都,1,36.0447089,139.3743599
六斗,1,36.0028345,140.1105419
木根,2,36.9430004,137.4747414
立山,1,36.5847934,137.6343407
荒川,1,36.1415564,139.8589857
独,5,41.2296285,141.0143767
君影,1,34.7205324,135.1428907
奈良,3,34.70489999999999,135.8384
上海,2,31.6688967,122.1137989
雲南,4,29.2233272,106.1977228
越,1,36.7995957,138.4063989
祇園,1,34.4529231,132.4693298
信濃,2,36.8707572,138.2803909
東山,1,35.010837,135.7914226
四谷,2,35.6726745,139.4551008
長野,1,36.835842,138.3190722
植木,1,33.6152803,130.5166492
```

## 登場回数と座標をもとにヒートマップを生成

先で生成した sada_places.csv に地域ごとの座標・登場回数が記録されているので、この情報を使ってヒートマップに反映させます。

ジオコーディングに Google Maps API を使用したので、ヒートマップも Google Maps API を使ってみました。

スタイルもスクリプトも HTML に書いてしまっていますが、コード量はこんな感じです。
※ヒートマップ表示には Google Maps API の API キーが必要です。下記コードをコピペしても動きませんのでご注意ください。

```html
<!DOCTYPE html>
<html>
  <head>
    <style>
      #map {
        width: 1200px;
        height: 600px;
      }
    </style>
    <script
  src="https://maps.googleapis.com/maps/api/js?key='write your API key'&libraries=geometry,visualization">
</script>
    <script>
      function initialize() {
        var mapCanvas = document.getElementById('map');
        var mapOptions = {
          center: new google.maps.LatLng(36.83566824724438,138.372802734375),
          zoom: 6,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        }
        var map = new google.maps.Map(mapCanvas, mapOptions)

        var heatmapData = [
         //座標の数だけオブジェクトが並ぶ。長いので中略。
         //間違いなく外部ファイル化できてる方が良い
         { weight :  2 ,  location :  new google.maps.LatLng(32.7361422,129.8708733) },
         { weight :  4 ,  location :  new google.maps.LatLng(71.3868712,-129.9945562) }, 
         { weight :  3 ,  location :  new google.maps.LatLng(37.5933274,139.0009869) }
        ]
        var heatmap = new google.maps.visualization.HeatmapLayer({
          data: heatmapData,
          radius: 50,
          map: map
        });
      }
      google.maps.event.addDomListener(window, 'load', initialize);
    </script>
  </head>
  <body>
    <div id="map"></div>
  </body>
</html>
```

参考にしたページ

* [Google Maps Heatmapレイヤを使う - Qiita](http://qiita.com/key/items/4e669b146874b1074be7)
* [Google Mapでヒートマップを作成 - watariseinの日記](http://watarisein.hatenablog.com/entry/2015/10/25/153843)

## 結果

### 日本地図

![日本地図](http://f.cl.ly/items/2y451J0l0k1G2u0x1g2l/heatmap-japan.png)

結果を見てみると、予想通りまっさんゆかりの東京・長崎が最も明るいです。
『広島の空』の広島や『昨日・京・奈良、飛鳥・明後日』『修二会』で登場する京都・奈良もそこそこ明るくなっています。

「北海道のやや右上が明るくなっているのはなんだろう？」と思い確認したところ、『日本』のジオコーディング結果がここでした...。

### 世界地図

![世界地図](http://f.cl.ly/items/1k2f0b0Z1s3P1r2s0a43/heatmap-world.png)

ズームを引いて世界地図で見てみると、日本以外の地域も数多く歌われている事が分かります。
歌手歴42年大ベテランのはずのまっさん、恐るべきグローバル人材...。

ライブで生歌を聴くたびに涙してしまう『風に立つライオン』のキリマンジャロの白い雪や、
実在した写真家の方をテーマに歌った『極光』『白夜の黄昏の光』で登場するあのアラスカも、ほのかに色付いています。

話逸れますが、『極光』『白夜の黄昏の光』は冬の夜空見ながら聴くととっても泣けるので、「聴いたことないよ」という方はこの機会に是非マスターしてみてください。
[「極光」と「白夜の黄昏の光」～さだまさしさんと阿岸充穂さん、そして星野道夫さん](http://36648998.at.webry.info/200912/article_8.html)

フランス・ドイツあたりも明るくなっていますが、予想以上に明るいようです。
これは品詞分解時に『仏』や『独』という単語が地域として解釈されたことによるものだったので、辞書追加していけば精度向上が見込めるかなと思っています。

# さいごに

さだまさし×ITアドベントカレンダー主催者さまが4日目に書かれていた『[さだまさしを kuromoji を用いて簡単に品詞分解してみる](http://qiita.com/moaikids/items/7bcdcc3648c71beb7806)』の一部内容と思いっきりネタ被り＆ヒートマップの結果が薄い内容になってしまって、お恥ずかしい限りです。

実際にやってみて、やっぱりスカイツリーや心字池も表示に反映させたい＆Google Maps API でのジオコーディング結果が一部「？」なところもあったので、しっかりと準備と勉強の時間をとって、あらためてヒートマップ作りに再挑戦したいと思いました。

面白い結果が出たら、生さだにハガキ投稿したいなぁ...。