【Python】位置情報解析ライブラリscikit-mobilityについて①  ~scikit-mobilityとは?~

# 1.  scikit-mobilityとは？
 scikit-mobilityは位置情報データを使用して人の動きを解析したり、可視化することができるpythonライブラリです。

公式ドキュメント：https://scikit-mobility.github.io/scikit-mobility/index.html
GitHub：https://github.com/scikit-mobility/scikit-mobility
公式ドキュメントは英語しかありませんが結構充実していて、
GitHubにはチュートリアル等も載っているので試してみるのがおすすめです。

# 2.  scikit-mobilityを使ってできること
scikit-mobilityでできることについてscikit-mobilityの[公式ドキュメント](ttps://scikit-mobility.github.io/scikit-mobility/index.html)([GitHub](https://github.com/scikit-mobility/scikit-mobility))に記載されていたので、引用します。

> scikit-mobility is a library for human mobility analysis in Python. 
The library allows to:
> 
> represent trajectories and mobility flows with proper data structures, TrajDataFrame and FlowDataFrame.
> 
> manage and manipulate mobility data of various formats (call detail records, GPS data, data from social media, survey data, etc.);
> 
> extract mobility metrics and patterns from data, both at individual and collective level (e.g., length of displacements, characteristic distance, origin-destination matrix, etc.)
> 
> generate synthetic individual trajectories using standard mathematical models (random walk models, exploration and preferential return model, etc.)
> 
> generate synthetic mobility flows using standard migration models (gravity model, radiation model, etc.)
> 
> assess the privacy risk associated with a mobility data set

scikit-mobilityでできることは、
* TrajDataFrameとFlowDataFrameという適切なデータ構造に変換することで、軌道と移動の流れを表現することができるようになります。

* 様々な形式のモビリティデータ（通話明細、GPSデータ、ソーシャルメディアからのデータ、調査データなど）を管理し、操作することができます。

* 個人レベル、集団レベルの両方において、データから移動の指標やパターンを抽出することができます。（例：移動の長さ、特徴的な距離、出発地-到着地のマトリックス、など）


* 標準的な数学的モデル（ランダムウォークモデル、探索・優先帰還モデルなど）を用いて、個人の合成軌道を生成することができます。

* 標準的な移動モデル（重力モデル、放射線モデルなど）を用いて、合成モビリティフローを生成することができます。

* モビリティデータセットに関連するプライバシーリスクの評価を行うことができます。

# 3. scikit-mobility内で使用できる関数について
位置情報データを解析や、加工ができる関数が多く実装されています。
大まかなカテゴリとそれぞれのAPIリファレンス、GitHubの該当箇所を紹介します。
* Dataframeを適切なデータ構造(TrajDataFrame, FlowDataFrame)に変換する関数
    * [API リファレンス](https://scikit-mobility.github.io/scikit-mobility/reference/data_structures.html)
    * [GitHub TrajDataFrame](https://github.com/scikit-mobility/scikit-mobility#create-a-trajdataframe)
    * [GitHub FlowDataFrame](https://github.com/scikit-mobility/scikit-mobility#create-a-flowdataframe)
* 位置情報データのクレンジング(前処理)を行う関数
  * [API リファレンス](https://scikit-mobility.github.io/scikit-mobility/reference/preprocessing.html)
  * [GitHub 前処理(preprocessing)](https://github.com/scikit-mobility/scikit-mobility#trajectory-preprocessing)
* 位置情報データの解析(個人レベル, 集団レベル)を行う関数
    * [API リファレンス](https://scikit-mobility.github.io/scikit-mobility/reference/measures.html)
    * [GitHub 位置情報データ解析(measures)](https://github.com/scikit-mobility/scikit-mobility#measures)
    * [APIリファレンス 集団レベルの解析(Collective measures)](https://scikit-mobility.github.io/scikit-mobility/reference/collective_measures.html)
    * [APIリファレンス 個人レベルの解析(Individual measures)](https://scikit-mobility.github.io/scikit-mobility/reference/individual_measures.html)
    * [APIリファレンス 評価用関数](https://scikit-mobility.github.io/scikit-mobility/reference/evaluation_measures.html)
* モデルを使用して入力データから行動や人口の流量を予測し、合成データを生成する関数
  * [API リファレンス](https://scikit-mobility.github.io/scikit-mobility/reference/models.html) 
  * [GitHub individual_models](https://github.com/scikit-mobility/scikit-mobility#individual_models)
  * [GitHub collective-generative-models](https://github.com/scikit-mobility/scikit-mobility#collective-generative-models)
* 位置情報データに関するプライバシーリスクの評価を行うことができる関数
  * [APIリファレンス](https://scikit-mobility.github.io/scikit-mobility/reference/privacy.html)
  * [GitHub privacy](https://github.com/scikit-mobility/scikit-mobility#privacy)

# 4. scikit-mobilityで使用するデータ形式について
## TrajDataFrame
scikit-mobility では、移動の軌道を表す緯度経度データは TrajDataFrameに変換して使用することができます。
TrajDataFrame は多くの軌道を含むことができ、TrajDataFrame の各行は軌道のポイントを表します。
> latitude(type: float);　緯度
> longitude (type: float);　経度
> datetime (type: date-time); 日時

主に上記の3つの必須カラムで構成されています。
さらに、2つのオプションのカラムを指定することができます。

> uid (type: string)；どのユーザーのデータなのかを識別するidを指定できます。
> tid (type: string); 一連の移動について識別idを指定できます。

## FlowDataFrame
scikit-mobilityでは、起点と終点の行列は、FlowDataFrameに変換することができます。FlowDataFrameの各行は、2つの場所間(起点と終点)のオブジェクトのフローを表します。

> origin (type: string);　起点
> destination (type: string);　終点
> flow (type: integer); フロー
上記の3つの必須カラムによって構成されています。

# 5. チュートリアル
GitHubにあるチュートリアルを少し紹介します。
Google Colaboratory等でも簡単に実行できます。
チュートリアルのURLは[こちら](https://github.com/scikit-mobility/scikit-mobility#tutorials)

## TrajDataFrameへの変換
今回は、この後の回で紹介していく関数によく使用するTrajDataFrameのデータの作成と、可視化についてのチュートリアルを紹介します。

```python
import skmob
data_list = [[1, 39.984094, 116.319236, '2008-10-23 13:53:05'], 
             [1, 39.984198, 116.319322, '2008-10-23 13:53:06'], 
             [1, 39.984224, 116.319402, '2008-10-23 13:53:11'], 
             [1, 39.984211, 116.319389, '2008-10-23 13:53:16']]
tdf = skmob.TrajDataFrame(data_list, latitude=1, longitude=2, datetime=3)
print(tdf.head())
```
```
   0        lat         lng            datetime
0  1  39.984094  116.319236 2008-10-23 13:53:05
1  1  39.984198  116.319322 2008-10-23 13:53:06
2  1  39.984224  116.319402 2008-10-23 13:53:11
3  1  39.984211  116.319389 2008-10-23 13:53:16
```
→ データはデータフレームからだけでなくリストから変換することも可能なようです。

もちろんデータフレームを変換することもできます。
```python
import pandas as pd
# 先ほどのリストをpandas.DataFrameに変換
data_df = pd.DataFrame(data_list, columns=['user', 'latitude', 'lng', 'hour'])
print(type(data_df))
```

```
<class 'pandas.core.frame.DataFrame'>
```
→型を確認するとDataFrameになっています。
```python
# DataFrameをTrajDataFrameに変換
tdf = skmob.TrajDataFrame(data_df, latitude='latitude', datetime='hour', user_id='user')
print(type(tdf))
print(tdf.head())
```
→ データ型とデータの中身を確認
```
<class 'skmob.core.trajectorydataframe.TrajDataFrame'>

   uid        lat         lng            datetime
0    1  39.984094  116.319236 2008-10-23 13:53:05
1    1  39.984198  116.319322 2008-10-23 13:53:06
2    1  39.984224  116.319402 2008-10-23 13:53:11
3    1  39.984211  116.319389 2008-10-23 13:53:16
```

自分のお好みのファイルからTrajDataFrameに変換することも可能です。
今回はチュートリアルに従って[こちら](https://raw.githubusercontent.com/scikit-mobility/scikit-mobility/master/examples/geolife_sample.txt.gz)のGitHubにあるデータをお借りしてファイルからデータを取ってきます。
※自動でデータがダウンロードされるので気をつけてください

```python
# ファイルのダウンロード(google colab等で実行する場合はこうすると楽です。)
import urllib.request
url='https://raw.githubusercontent.com/scikit-mobility/scikit-mobility/master/examples/geolife_sample.txt.gz'
save_name='geolife_sample.txt.gz'
urllib.request.urlretrieve(url, save_name)

# TrajDataFrameへの変換
tdf = skmob.TrajDataFrame.from_file('geolife_sample.txt.gz', latitude='lat', longitude='lon', user_id='user', datetime='datetime')
print(tdf.head())
```
中身を確認すると以下のようになります。先ほどの作成したデータと違ってuidが指定されていて、
データに対してユーザー分けがなされていることがわかります。
```
         lat         lng            datetime  uid
0  39.984094  116.319236 2008-10-23 05:53:05    1
1  39.984198  116.319322 2008-10-23 05:53:06    1
2  39.984224  116.319402 2008-10-23 05:53:11    1
3  39.984211  116.319389 2008-10-23 05:53:16    1
4  39.984217  116.319422 2008-10-23 05:53:21    1
```
この緯度経度の羅列だと全くイメージが湧かないので、データをセットの特徴を掴むために可視化してみます。
TrajDataFrameでは簡単にデータを地図上に可視化できるようになっています。
以下を実行します。
```python
tdf.plot_trajectory(zoom=12, weight=3, opacity=0.9, tiles='Stamen Toner')
```
引数の役割としては、
* zoom: 地図をどれくらいズーム表示した状態で出力するか指定できます
* weight: 地図上に描画する線の太さを指定できます
* opacity: 地図上に描画する線の透過度を指定できます
* tiles: バックグラウンドの地図の種類を選択できます
他にも色々指定できるので好きなように可視化して表現することができます。
(公式ドキュメントに詳しく載っています。)

出力される画像はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/c7d04981-88be-5bd9-b0a1-0b9336c51764.png)

ユーザー二人分の移動履歴のデータが地図上に可視化されました。
これでこのデータが北京のユーザーのデータであることなどがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/7bc4eee1-cd73-3373-07d3-b5548a5c72d3.png)

また、緑と赤のマーカーはそれぞれユーザーの最初のログと最後のログを表しています。
マーカーをクリックすることでログの詳細を見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/44d1d88a-b859-4f02-59d8-86912d0f24eb.png)
地図は自由にズームができるので行動履歴全体をみてみたいときも簡単に描画できます。

ぜひ色々な位置情報データで試してみてください。


# 6. 参考URL
* https://scikit-mobility.github.io/scikit-mobility/index.html
* https://github.com/scikit-mobility/scikit-mobility
* https://qiita.com/igarashi4423/items/5e5763cf50c7a2c36d57

# 7. シリーズ記事
scikit-mobilityについて、これからシリーズの記事を投稿していく予定です。
記事が投稿されたらこちらにリンクを作成していきます。
* 第2回
    * [【Python】位置情報解析ライブラリscikit-mobilityについて② ~前処理編・前編~](https://qiita.com/Nightley_dev/items/5fcccc485aee2bd9a56a)
* 第3回
    * [【Python】位置情報解析ライブラリscikit-mobilityについて③ ~前処理編・後編~](https://qiita.com/Nightley_dev/items/3c5d361a3fcfae68daf9)

# 最後に
私たちの会社、ナイトレイでは一緒に事業を盛り上げてくれるGISチームメンバーを募集しています！
現在活躍中のメンバーは開発部に所属しながらセールス部門と密に動いており、
慣れてくれば顧客とのフロントに立ち進行を任されるなど、顧客に近い分やりがいを感じやすい
ポジションです。

 このような方は是非Wantedlyからお気軽にご連絡ください（もしくは recruit@nightley.jp まで）

 ✔︎ GISの使用経験があり、観光・まちづくり・交通系などの分野でスキルを活かしてみたい
 ✔︎ ビッグデータの処理が好き！（達成感を感じられる）
 ✔︎ 社内メンバーだけではなく顧客とのやり取りも実はけっこう好き
 ✔︎ 地理や地図が好きで仕事中も眺めていたい 

一つでも当てはまる方は是非こちらの記事をご覧ください 。
二つ当てはまった方は是非エントリーお待ちしております(^ ^)

「位置情報×モビリティ.まちづくりetc事業領域拡大の為GISエンジニア募集」 

https://www.wantedly.com/projects/1031814

▼ナイトレイとは？

https://www.wantedly.com/companies/nightley