そろそろバレンタインなのでラインのトーク履歴を可視化してみますかｗ

バレンタインだからってわけじゃなくてじゃないんですけど，最近Githubにあるあのコントリビューションのチャートが気になっていました．

自分のコントレビューション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/e3c44013-3b5d-90cc-8251-8008a9296bc0.png)

[@torvalds](https://github.com/torvalds)のコントリビューション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/1a9aadf7-9380-bed1-4ac0-d855e474fd87.png)

いい感じの時系列データがあれば似たようなチャートを試しに作ってみたいと前から思っていたところ，ちょうどラインのデータが簡単にダウンロードできるってことを知ったので，そのデータを使って作ってみました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/30ff7697-9c2c-1d81-053c-749468745fb5.png)


## Lineのトーク履歴を取得

ラインからトーク履歴のチャットデータを保存できるって知っていました？？
実は意外と簡単にできるもんなんです．

手順は[こちらのサイト](LINEでトーク履歴をメールで送信・Keepに保存)を参考にしています．画像のソースもそちらです．

1. LINEアプリから保存したいトークをタップします。
2. 右上の「V」をタップ＞「設定」をタップします。
![](https://www.copytrans.jp/app/uploads/sites/2/2013/12/line-talk-send-text.png)
3. 「トーク履歴を送信」から送信オプションを選択します。ここに、トーク履歴をKeepに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/7a806077-1634-1e34-c814-26bfb837309c.png)

4. Keepからトーク履歴にアクセスできます。
![](https://www.copytrans.jp/app/uploads/sites/2/2013/12/line-talk-txt-view-in-keep.png)

## CalmapとPandasでデータをすぐに可視化！

まず，以下のパッケージをインポートしていることにします．

```python
import datetime, calmap
import japanize_matplotlib
import pandas as pd

from matplotlib import pyplot as plt
from collections import defaultdict

import warnings
warnings.simplefilter("ignore")
```

そして次にデータの集め方について考えます．データ取得の工程に出てきたこちらの画像の右側にテキストデータがありますが，このようなフォーマットでデータを読み込むと仮定します．（※僕の携帯は英語設定なので，少しだけフォーマットが違いますが，ほとんど同じです！）


![](https://www.copytrans.jp/app/uploads/sites/2/2013/12/line-talk-txt-view-in-keep.png)

日付だけの行があって，その下に時間，人，チャット内容が一つの行になっていますね（電話・スタンプ・ファイルなども面倒なのでチャットして考える！）．ここに着目して，日付の行だったらTrueを返す，`isNewDay()`とチャットの行だったらTrueを返す`isChat()`関数を作ります．

| 日付       | |        |
|:-----------------:|:------------------:|:------------------:|
| 時間             |              人 |        内容        |
| 時間           |            人 |       内容       |
| 時間           |            人 |       内容       |

| 日付       | |        |
|:-----------------:|:------------------:|:------------------:|
| 時間             |              人 |        内容        |
| 時間           |            人 |       内容       |

```python
def isNewDay(line):
    line = line.strip().replace(' ','')
    elements = line.split(',')
    if len(elements) == 2:
        day, date = elements
        try:
            assert day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] 
            assert datetime.datetime.strptime(date, '%m/%d/%Y')
            return True
        except (AssertionError, ValueError) as e:
            pass
    return False

def isChat(line):
    elements = line.split('\t')
    if len(elements) == 3:
        time, person, activity = elements
        try:
            assert datetime.datetime.strptime(time, '%H:%M')
            assert person in [PERSON1, PERSON2]
            return True
        except (AssertionError, ValueError) as e:
            pass
    return False
```

もし読み込むデータのテキストファイルのフォーマットが若干違ったりすれば，これらの関数の内容を修正する必要があります．

ここまできたら，あとはループで日付毎にチャットの回数を数えれば良いです．僕はしたのようにdefaultdictを使って以下のように数えました．日付順にチャットが並んでいると仮定しているので結構ガバガバな感じで書いています(笑．

```python
d = defaultdict(lambda: 0)
with open(PATH_TO_DATA) as f:
    for line in f.readlines():
        # New day
        if isNewDay(line): 
            day, date = line.split(',') #
            month, day, year = list(map(int, date.split('/')))
            
        # Chat Event
        if isChat(line):            
            index = datetime.datetime(year, month, day)
            d[index] += 1
```

チャットの回数を数え上げたら，今度は可視化します．これには[calmap](https://pythonhosted.org/calmap/)パッケージを使います．
使い方はすごく簡単で，基本的には時系列上に並んでいるpandasのSeriesをぶちこめばOKです．

``` python
s = pd.Series(d)
calmap.calendarplot(s, monthticks=3, cmap='PuRd', daylabels='月火水木金土日',
                    fig_kws=dict(figsize=(8, 4)))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/c8c0ad4d-e90d-0a14-80b7-daace25f96d7.png)

色が薄いなと思ったら，以下のように重みをつけたりして強調させたりすることもできます．

```python
import ipywidgets as widgets
from ipywidgets import interact, interact_manual

@interact
def emph(x=(-0.5, 0.5, 0.1)):
    s = pd.Series(d)
    s *= s**x
    calmap.calendarplot(s, monthticks=3, cmap='PuRd', daylabels='月火水木金土日',
                    fig_kws=dict(figsize=(8, 4)))
    
```

![chrome-capture (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295666/8f52e61a-ac33-5e36-cd71-57b9250c11c3.gif)

以上です！メカブとか使ってさらに深く掘り下げていくのも面白そうですね．でも，もう疲れたので今日は以上ですー