Tumblr Facebook ВКонтакте linkedin Hatena Tweet LINE 카카오톡 Reddit Pocket Google+ 微博 Pinterest Email

都市経緯度データ一覧#雑用#プログラミング初歩

オープンなデータソースを探す

on-ze.comにて openweathermap.org のリストが紹介されていたが、本家はリンク切れ。本家を探すとjsonデータなどは出てくる。

simplemaps.comは有償が150万都市だが、無償版の12000都市では名古屋の隣が浜松、津といった具合。対するopenweathermapは74000都市で、名古屋の隣は春日井、小牧、瀬戸、知立、大府といった具合。(simplemaps.comは無償版もバックリンク等を紹介しろという条件。)

ウィキペディアから抜き出すという方法もあるが意外と形式が様々で割と難航するという記事が。(kesin.hatenablog.com)

ウィキペディア等ユーザー提出による場合は重複や重要性による取捨も検討しておかないと無駄にデータベースが巨大化しそう。わけのわからない字名だされるより疎なデータベースでTokyoとだけ出るほうがわかりやすい場合もある。用途による。

データ加工の話。

データベースのデータも完全に綺麗ではない。

headしてみたら出だしからFirozpur Jhirka。

819827	Razvilka	55.591667	37.740833	RU
524901	Moscow	55.752220	37.615555	RU
1271881	Firozpur Jhirka	27.799999	76.949997	IN
1283240	Kathmandu	27.716667	85.316666	NP
703448	Kiev	50.433334	30.516666	UA
1282898	Pokhara	28.233334	83.983330	NP
3632308	Merida	8.598333	-71.144997	VE
1273294	Delhi	28.666668	77.216667	IN
502069	Reshetnikovo	56.450001	36.566666	RU

とりあえず

head city_list.txt|awk '{printf $(NF-1)"; "$(NF-2)"; "$NF";";$1="";$(NF-2)="";$(NF-1)="";$NF="" ;print $0}'|awk -F"; " '{printf ("%4.2f",$1);printf ";";printf ("%4.2f",$2);printf ";";printf $3";"$4"\n"}'|sed 's| $||g'

として

37.74;55.59;RU;Razvilka
37.62;55.75;RU;Moscow
76.95;27.80;IN;Firozpur Jhirka
85.32;27.72;NP;Kathmandu
30.52;50.43;UA;Kiev
83.98;28.23;NP;Pokhara
-71.14;8.60;VE;Merida
77.22;28.67;IN;Delhi
36.57;56.45;RU;Reshetnikovo

一度111kmなので小数点以下ふた桁でkm,三桁とると100mスケールになってくるので、無駄なデータは捨てとく。(この処理で3.1MBが1.9MBになった。)

あとは

sort -hk1

で経度順にでも並べておいたりする。

区切り文字の選定

だいたい、コンマは地名にありふれているので絶対使えない。

grep ",*," city_list.txt
1690086	Poblacion, San Felipe	15.062220	120.070000	PH
2516372	Xeraco,Jaraco	39.033329	-0.216670	ES
6292397	Rueti / Dorfzentrum, Suedl. Teil	47.253681	8.856540	CH
6615444	Oliver-Valdefierro, Oliver, Valdefierro	41.644539	-0.933490	ES
4140963	Washington, D. C.	38.895111	-77.036369	US
7874740	Villa Presidente Frei, Nunoa, Santiago, Chile	-33.460690	-70.580238	CL
2949482	Beverstedt, Flecken	53.434132	8.819150	DE

grep ";JP;"|wc -l

とすると日本国内は丁度770都市ですね。

同様に調べると、KR 120,KP 74,CN 1020,TW 20、となっているので、日本国内は面積の割にかなり密にデータがある印象。他の国ではかなり雑なデータという印象を与える可能性も。

ここまでの話。

cat city_list.txt|awk '{printf $(NF-1)"; "$(NF-2)"; "$NF";";$1="";$(NF-2)="";$(NF-1)="";$NF="" ;print $0}'|awk -F"; " '{printf ("%4.2f",$1);printf ";";printf ("%4.2f",$2);printf ";";printf $3";"$4"\n"}'|sed 's| $||g'|sort -hk1 > tmp

ついでにSQLITEに取り込んでみる。

ターミナルからデータベースを指定して開始。

sqlite3 /home/username/city.db

.show

と打ってセパレーターなど確認。

先ほどセパレーターは;セミコロンにしたから、

.separator ;

としてセパレーターを切り替えておく。

CREATE TABLE IF NOT EXISTS city(`LNG`, `LAT`, `COUNTRY`, `CITY`);

四項目のテーブルcityをつくる。行末は必ずコロン。

で、

.import "tmp" city

とすると、先ほどの/home/username/city.dbが2.5MBに膨らみました。

.import .quit のような命令は行末セミコロンが不要ですが行頭ピリオドが必須。

余談

各列、データの型を指定できるので、数値をテキストではないと明言すればデータサイズは減らせるはずですが、

CREATE TABLE IF NOT EXISTS city(`LNG` NUMERIC, `LAT` NUMERIC, `COUNTRY` TEXT, `CITY` TEXT);

とすると逆に2.9MBに膨らんでしまいました。

sqliteのデータベースはcatしても平文で投げ込まれてるだけなので、なんか芸がないなという感じです。

ここで

select abs(lat-35)+abs(lng-137),city FROM city ORDER by abs(lat-35)+abs(lng-137) asc limit 1;

とすれば簡易的に最も近い地名を得られますね。極めて雑な計算ですが。

select abs(lat-35)+abs(lng-137),city FROM (select * from city where lng like '13%') ORDER by abs(lat-35)+abs(lng-137) asc limit 1;

とすれば計算が減って早くなる。

2018-12-18

//
::
//
::

2019 B-AE.com All rights reserved.

support @ b-ae.com

Flag Counter