日本のOSMデータへのコントリビューター(マッパー)数の推移
OpenStreetMap(OSM)は,この記事を執筆している2020年8月時点で,累計のコントリビューター(マッパー)数が,全世界で670万を超えるグローバルな活動となっています.OpenStreetMap stats reportつい最近,OSM-Notesという機能を使った地理的分布に関する分析を国際誌に掲載しましたが,他方,数年前からの研究で日本のOSMのコントリビューター(マッパー)数を把握したいと考え,当時まだほとんど使われていなかったOSMの履歴データ付きのダンプデータ* を使ってユーザー動向を集計するスクリプトを開発いただいた事があることをふと思い出しました.
*: ダンプデータは,Geofabrikのサイト内で,OSMコントリビューター向けに,japan-internal.osh.pbfを提供しています.ただし,このデータはGDPR施行にともない,user IDやチェンジセットなどの履歴データは,OSMのアカウントを持っているユーザーのみが入手できるようになっています.https://download.geofabrik.de/asia/japan.html
時期的に,OSMも16周年の誕生日を迎えたということもあり,当時のスクリプトを使って久しぶりに集計を試みてみました.なお,該当の日本国内のoshデータは,2020年8月時点で.osh.pbf形式(圧縮された状態)で2.93GBあるようです.
月次ユーザー数抽出用のPythonスクリプトは,OSMデータのハンドリングライブラリである「osmium」がべースになっており,基本的な流れとしては,osh.pbfから,月を集計単位として,ユーザーごとの最初の編集日を取得した上で日ごとに積み上げてCSV形式で出力するものです.実際には一括処理するプログラム等もあるのですが,当時は探索的に試行したかったこともあり,幾つかのスクリプトに分かれています.
2008年から2020年7月までの日本国内のOSMデータを編集したマッパー数の推移
月次別のマッパー数
日本のOSMで最初の大きな波は,2011年3月期の東日本大震災に関わるマッピングで月間484ユニークユーザーでした.全期間の平均は,545ユーザー(赤い点線)で初めて平均値を上回ったのは,2012年10月でした.ちょうど,前月の2012年9月には,アジア圏では初めて,OpenStreetMapの国際会議「State of the Map(SotM) 2012 Tokyo」が開催されたタイミングであったことも関わっているかもしれません.
月間ユニークユーザー数が1000という大台を初めて超えたのは,4年後の2016年4月期で,熊本地震におけるマッピング活動が少なからず影響していそうです.参考:2016年4月熊本地震_地図・地理空間情報関連まとめ.それ以降,月間1000ユーザーが平均的な値となり,2018年6月〜7月には1500ユーザーを上回りました.月間最大のユニークユーザー数となったのは,2019年10月の2922ユーザーでした.
ちなみに日次ベースでは,OSMの各種のリアルタイム集計を公開しているNies One !によると,日本では1日あたり約100(20位前後),世界第一位になることが多いドイツでは約690のようです.参考:OSM Stats
マッパーが最初に日本を編集した時期
次に,マッパーが最初に日本を編集した月を編集したものですが,先程示した結果と同様に2011年3月期と2012年10月期,2016年4月などに大きな波がありました.これより前に日本以外を最初に編集したマッパーも多少いることも考えられますが,OSM参加のきっかけに2つの時期・イベントが大きなタイミングになっているといえるでしょう.平均すると230くらいになるようですが,2016年4月以降は,月間の新規マッパー数が500を超える月が度々ありました.マッピングパーティ活動がそれまで盛んだった京都(関西)や東京近郊以外に全国に広がりつつある時期とも重なっているようで,こうした現地でのフィールド活動による新規参加という側面は大きいと思います.2020年1月以降は,平均よりもやや少ない状況にあり,マッピングパーティがCOVID-19における外出自粛で開けないというの要因もあったのかもしれません.他方,再び2020年7月には1200ユーザーを超える新規の登録があったようです.
累計値としての日本国内を編集したマッパー
月ごとの集計では,同一アカウントのユーザーが,毎月編集する場合,各月にカウントするため,ユニークユーザーベースで,累積的なマッパー数も示しておきます.日本国内を編集したマッパーを累計すると,2011年1月に初めて1000ユーザーを超えました.その後,2016年4月に10000ユーザーを超えて,やや増加スピードが上がっているようにも見受けられます.2019年9月から10月にかけては約2000ユーザー増えており,これまでの累計値として35000ユーザーに近づきつつあります.OSMの活動を知って新しく参加したいと思うユーザーが増えてくれると良いと思う一方で,OSMのコミュニティのなかでも予てから議論にあるように,マッパーのモチベーション(持続性・継続性)という部分もあり,特に近年参加されたマッパーがどの程度活動を定期的に行っている/もしくは離脱している,かについてもさらに集計等の分析は進める必要があります.
集計に使ったPythonスクリプト
- 本スクリプトは,@smellman に開発いただきました.ありがとうございました!
import osmium as o
import csv
from datetime import datetime, timezone
class UserReader(o.SimpleHandler):
def __init__(self, from_date = None, to_date = None):
o.SimpleHandler.__init__(self)
self.user_list = {}
self.from_date = from_date
self.to_date = to_date
self.check_date_range = (from_date != None and to_date != None)
def node(self, n):
self._add(n)
def way(self, w):
self._add(w)
def relation(self, r):
self._add(r)
def _add(self, obj):
if self.check_date_range:
if obj.timestamp > self.to_date:
return
if obj.timestamp <= self.from_date:
return
if obj.user_is_anonymous():
return
if obj.uid in self.user_list:
current = self.user_list[obj.uid]
if current["timestamp"] > obj.timestamp:
self._insert(obj)
else:
self._insert(obj)
def _insert(self, obj):
self.user_list[obj.uid] = {
"timestamp": obj.timestamp,
"user": obj.user
}
def output_csv(input_hash, output_file):
with open(output_file, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["uid", "name", "first modified time"])
for key, value in input_hash.items():
writer.writerow([str(key), value["user"], value["timestamp"].isoformat()])
def date_string(string):
value = None
try:
value = datetime.strptime(string, '%Y%m%d').replace(tzinfo=timezone.utc)
except ValueError:
msg = "%r is not a date string" % string
raise argparse.ArgumentTypeError(msg)
return value
if __name__ == '__main__':
import argparse
p = argparse.ArgumentParser(description="OSM data (osm / osh.pbf) to csv")
p.add_argument("input_file", help="Input file")
p.add_argument("output_file", help="Output file")
p.add_argument("from_date", nargs="?", help="From date (yyyyMMdd)",
type=date_string)
p.add_argument("to_date", nargs="?", help="To date (yyyyMMdd)",
type=date_string)
args = p.parse_args()
# read
handler = UserReader(args.from_date, args.to_date)
handler.apply_file(args.input_file)
# write
output_csv(handler.user_list, args.output_file)
さらに便利な分析プラットフォームの登場も
import osmium as o
import csv
from datetime import datetime, timezone
class UserReader(o.SimpleHandler):
def __init__(self, from_date = None, to_date = None):
o.SimpleHandler.__init__(self)
self.user_list = {}
self.from_date = from_date
self.to_date = to_date
self.check_date_range = (from_date != None and to_date != None)
def node(self, n):
self._add(n)
def way(self, w):
self._add(w)
def relation(self, r):
self._add(r)
def _add(self, obj):
if self.check_date_range:
if obj.timestamp > self.to_date:
return
if obj.timestamp <= self.from_date:
return
if obj.user_is_anonymous():
return
if obj.uid in self.user_list:
current = self.user_list[obj.uid]
if current["timestamp"] > obj.timestamp:
self._insert(obj)
else:
self._insert(obj)
def _insert(self, obj):
self.user_list[obj.uid] = {
"timestamp": obj.timestamp,
"user": obj.user
}
def output_csv(input_hash, output_file):
with open(output_file, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["uid", "name", "first modified time"])
for key, value in input_hash.items():
writer.writerow([str(key), value["user"], value["timestamp"].isoformat()])
def date_string(string):
value = None
try:
value = datetime.strptime(string, '%Y%m%d').replace(tzinfo=timezone.utc)
except ValueError:
msg = "%r is not a date string" % string
raise argparse.ArgumentTypeError(msg)
return value
if __name__ == '__main__':
import argparse
p = argparse.ArgumentParser(description="OSM data (osm / osh.pbf) to csv")
p.add_argument("input_file", help="Input file")
p.add_argument("output_file", help="Output file")
p.add_argument("from_date", nargs="?", help="From date (yyyyMMdd)",
type=date_string)
p.add_argument("to_date", nargs="?", help="To date (yyyyMMdd)",
type=date_string)
args = p.parse_args()
# read
handler = UserReader(args.from_date, args.to_date)
handler.apply_file(args.input_file)
# write
output_csv(handler.user_list, args.output_file)
@higa4 さんの記事「OSM日本の地物量推移(2007-2019)にも詳細に書かれていますが,ハイデルベルグ大学の地理情報技術研究所(HeiGIT)が,開発・運用しているohsomeは,OpenStreetMap(OSM)履歴データ分析のプラットフォームとして非常に便利なインターフェースやAPI,DBをオープンソースとして提供しています.
なかでも,各種整備されたAPIを使うことで,様々な単位でどの地域でも集計が可能で,ohsome dashboardでは処理できない,地物ごとのコントリビューター(マッパー)数の集計などといったかなりカスタマイズされた統計なども抽出することができるようです.
- 参考となるドキュメンテーション
機会があれば,こちらの方でも同様の作業ができるか試してみたいところです.
分析に使った元データについて
© OpenStreetMap contributors https://www.openstreetmap.org/copyright
この記事を書くにあたっては OpenStreetMap のデータを利用しています。データの著作権は OpenStreetMap の貢献者に帰属されています。
Author And Source
この問題について(日本のOSMデータへのコントリビューター(マッパー)数の推移), 我々は、より多くの情報をここで見つけました https://qiita.com/tosseto/items/24972f597b53150d81f1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .