【Python】位置情報解析ライブラリ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にはチュートリアル等も載っているので試してみるのがおすすめです。

scikit-mobilityの主な機能と、チュートリアルについて解説しているQiitaもありますのでこちらも是非参考にしてください。
* [【Python】位置情報解析ライブラリscikit-mobilityについて① ~scikit-mobilityとは?~](https://qiita.com/Nightley_dev/items/02b8fbad2db8236a92d1)


# 2. 今回紹介する関数
* カテゴリ：measures(データ解析用関数)
* 参考URL：https://scikit-mobility.github.io/scikit-mobility/reference/measures.html
* 概要：緯度・経度・日時・ユーザーid等のデータから様々な移動パターンの解析を行うことができる関数が用意されています。

また、データ解析用の関数には二種類のカテゴリがあります。
1. [Collective measures(集団解析) :　データセット全体の人流データの動きを解析できる関数](https://scikit-mobility.github.io/scikit-mobility/reference/collective_measures.html)
1. [Individual measures (個別解析)：データセット内のユーザーそれぞれの動きを解析できる関数](https://scikit-mobility.github.io/scikit-mobility/reference/individual_measures.html)

今回はこのうち
```Individual measures (個別解析)```
に分類される17個の関数のうち以下の6つの関数を、コードを交えて紹介していきます。

* **radius_of_gyration**：ユーザーの特徴的な移動距離を算出する関数
* **k_radius_of_gyration**：ユーザーの最も頻度の高いk個の場所からの特徴的な移動距離を算出する関数
* **random_entropy**：ユーザーのランダムエントロピーを算出する関数
* **uncorrelated_entropy**： 各場所の履歴確率からユーザーの訪問パターンの特徴を算出する関数
* **real_entropy**：「移動パターン」に存在する時空間的な特徴の予測可能確率を算出する関数
* **jump_lengths**：時系列順に並んだ2つの連続した各ポイント間の距離を算出する関数


**※ 今回この記事で使用しているデータは社内検証用のデータになります。**
# 3. 前提処理
## ライブラリのインストール
``` 
$ pip install scikit-mobility
```
詳しい環境構築は[こちら](https://github.com/scikit-mobility/scikit-mobility#installation)を参考にしてください

## TrajDataFrameデータの作成
* 以下の項目を含むデータを用意します。
> latitude(type: float);　緯度(必須)
> longitude (type: float);　経度(必須)
> datetime (type: date-time); 日時(必須)
> uid (type: string)；(オプション)
> tid (type: string); (オプション)

特に使いたいデータがない場合はscikit-mobilityのチュートリアルを参考に[こちらのデータ](https://raw.githubusercontent.com/scikit-mobility/scikit-mobility/master/examples/geolife_sample.txt.gz)をダウンロードするといいと思います。
※自動でデータがダウンロードされるので気をつけてください

```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に変換します。

```python
import skmob
# リストをTrajDataFrameに変換する場合
tdf = skmob.TrajDataFrame(data_list, latitude=1, longitude=2, datetime=3)
# pandas.DataFrameをTrajDataFrameに変換する場合
tdf = skmob.TrajDataFrame(data_df, latitude='latitude', datetime='hour', user_id='user')
```


# Individual measures (個別解析)
参考URL：https://scikit-mobility.github.io/scikit-mobility/reference/individual_measures.html

## 概要
入力したuidごとの移動履歴、行動パターンを解析する関数が所属しています。


## radius_of_gyration
### 概要
各ユーザーの特徴的な移動距離を算出する関数

### inputに必要なデータとパラメータ、outputされるデータについて
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * show_progress: Trueの場合、プログレスバーを表示。
* inputデータ例
  * データ型はTrajDataFrameのデータを使用します。
![Screen Shot 2022-11-22 at 20.27.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg)

* outputデータ
  * 各ユーザーの特徴的な移動距離(回転半径)を算出します。
  * outputされるデータ例
      <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6d1adc65-57da-b989-7cd8-7164cea9d53e.png' width=80% >
  * uidとradius_of_gyrationのカラムを含むデータが出力されます。
  * ユーザーidとそれに対応するユーザーの特徴的な移動距離がわかります。
  * **特徴的な移動距離**の内容が理解できておらず勉強中です。。
  * 習慣（よくあるパターン）的な特徴なのか、珍しい移動的な特徴なのかが未だわからずといった感じです。
* コード例
    ```python
    from skmob.measures.individual import radius_of_gyration
    rg_df = radius_of_gyration(tdf)
    rg_df.head(10)
    ```

##  k_radius_of_gyration
### 概要
ユーザーの最も頻度の高いk個の場所からの特徴的な移動距離(k回回転半径)を算出する関数
### inputに必要なデータとパラメータ、outputされるデータ
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * k: 最も頻繁に訪れる場所の数(デフォルトは２)
  * show_progress: Trueの場合、プログレスバーを表示
* inputデータ例
  * データ型はTrajDataFrame。
![Screen Shot 2022-11-22 at 20.27.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg)

* outputデータ
  * 各ユーザーの最も頻度の高いk個の場所からの特徴的な移動距離をuidごとに算出します。
  * outputされるデータ例
  <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/32e4e320-0e96-c249-46c8-9d1968dbf02e.jpeg' width=80% >

* コード例
    ```python
    from skmob.measures.individual import k_radius_of_gyration
    krg_df = k_radius_of_gyration(tdf)
    krg_df.head(10)
    ```

## random_entropy
### 概要
各ユーザーのランダムエントロピー(予測可能性)を算出する関数

### inputに必要なデータとパラメータ、outputされるデータ
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * show_progress: Trueの場合、プログレスバーを表示
* inputデータ例
  * データ型はTrajDataFrame。
![Screen Shot 2022-11-22 at 20.27.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg)
* outputデータ
  * 各ユーザーの居場所の予測可能性が算出されます。
  * outputされるデータ例
      <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/b169c464-3a23-37cf-4b11-1b863418d69c.jpeg' width=70% >

* コード例
    ```python
    from skmob.measures.individual import random_entropy
    re_df = random_entropy(tdf)
    re_df.head(10)
    ```

## uncorrelated_entropy 
### 概要
各場所の履歴確率からユーザーの訪問パターンの特徴を算出する。
### inputに必要なデータとパラメータ、outputされるデータ
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * normalize: Trueの場合範囲内のエントロピーを正規化
  * show_progress: Trueの場合プログレスバーを表示

* inputデータ例
  * データ型はTrajDataFrame。
![Screen Shot 2022-11-22 at 20.27.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg)
* outputデータ
  * 各ユーザーの訪問パターンの特徴のエントロピーを算出
  * outputされるデータ例
      <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/5aa9e65f-8eb0-0548-0787-c7cc79618d58.jpeg' width=80% >

* コード例
    ```python
    from skmob.measures.individual import uncorrelated_entropy
    ue_df = uncorrelated_entropy(tdf, normalize=True)
    ue_df.head(10)
    ```

## real_entropy
### 概要
訪問頻度、訪問した場所の順序や各場所に滞在した時間から、「移動パターン」に存在する時空間的な特徴の予測可能確率を算出する

### inputに必要なデータとパラメータ、outputされるデータ
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * show_progress: Trueの場合、プログレスバーを表示

* inputデータ例
  * データ型はTrajDataFrame。
![Screen Shot 2022-11-22 at 20.27.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg)

* outputデータ
  * 各ユーザーの移動パターンの特徴の予測可能確率をuidごとに算出します。
  * outputされるデータ例
    <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/7bb07571-e65c-7a38-f123-98f0d4ebe998.jpeg' width=65% >

* コード例
    ```python
    from skmob.measures.individual import real_entropy
    rtdf = tdf.sort_values(by="datetime")
    re_df = real_entropy(rtdf) 
    re_df.head(10)
    ```

## jump_lengths
### 概要
時系列順に並んだ2つの連続した各ポイント間の距離を算出する
### inputに必要なデータとパラメータ、outputされるデータ
* inputデータ
  * tdf(TrajDataFrame): 緯度経度データ
* パラメータ
  * show_progress: Trueの場合、プログレスバーを表示
  * merge: Trueの場合、個人のリストを１つのリストにマージする

* inputデータ例
  * データ型はTrajDataFrame。
  * **inputデータは、datetimeで昇順に並べ替える必要があります。**
    <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/6826083f-55e0-42ea-1c15-a539924e1f1a.jpeg' width=100% >

* outputデータ
  * uidごとに各ポイント間の距離を算出し、表示します。
  * merge=Falseの場合は、pandas.DataFrameで出力されます。
  * outputされるデータ例
      <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/8a65bfe8-389e-6ec9-9e98-2e1332a30f5f.jpeg' width=80%>
  * merge=Trueの場合は、listで出力されます。
      <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/49714d2f-1dc4-fa4b-cdcc-51870540ddfe.png' width=200%>
  * uid関係なく全件のデータがlistにまとめられてしまうようなので、データを入れる前にuidごとに処理できるようにする一工程必要そうです。

* コード例
    ```python
    from skmob.measures.individual import jump_lengths
    jl_df = jump_lengths(tdf)
    jl_df.head(10)
    # mergeあり
    jl_list = jump_lengths(tdf, merge=True)
    ```

# 5. シリーズ記事
scikit-mobilityについて、シリーズで記事を投稿しています。
シリーズの記事もぜひ読んでいただけると嬉しいです。

前回の記事はこちらです。
* [【Python】位置情報解析ライブラリscikit-mobilityについて④ ~データ解析編・人流データ全体解析~](https://qiita.com/Nightley_dev/items/01c3b81ad25580a33697)



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

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

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

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

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

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

▼ナイトレイとは？

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