32
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

さだまさし x ITAdvent Calendar 2015

Day 21

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

Posted at

はじめに

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

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

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

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

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

やったこと(ざっくり)

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

やったこと(詳細)

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

歌詞取得

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

品詞分解

品詞分解には Python の形態素解析ライブラリ janome を使用しました。

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()

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

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

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

janome の詳細な仕組みや歴史については、中の方のスライド『Pyconjp2015 - Python で作って学ぶ形態素解析』がありますのでご参照ください。(2015年生まれなんですね!ありがたや!)

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

地域を抽出

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

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 ドキュメントによると、辞書フォーマットは Mecab と一緒だそうです。

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

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

(おことわり)

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

ジオコーディング

ジオコーディングには、これまた Python の googlemaps ライブラリを使用しました。

Google Maps API を利用することになるので、API キーの指定が必要です。
取得方法は googlemaps の GitHub に記載されています。

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']

ここまでまとめ

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

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()

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

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 キーが必要です。下記コードをコピペしても動きませんのでご注意ください。

<!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>

参考にしたページ

結果

日本地図

日本地図

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

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

世界地図

世界地図

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

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

話逸れますが、『極光』『白夜の黄昏の光』は冬の夜空見ながら聴くととっても泣けるので、「聴いたことないよ」という方はこの機会に是非マスターしてみてください。
「極光」と「白夜の黄昏の光」~さだまさしさんと阿岸充穂さん、そして星野道夫さん

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

さいごに

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

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

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

32
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?