ツイート時刻から生活リズムの可視化をする

もう10年も前の映画になるらしいですが、デスノートでLが被害者の死亡時刻を重ねると容疑者が大学生であることを割り出すシーンがあったのを覚えていますか?
あるいはGitHubでPunch cardって出るじゃないですか。なんとなく格好良くて好きです。
同じようなことがtweet時刻でも出来るのではないかと考え、tweet時刻から生活リズムが見えるか調べてみました。

やったこと

  • Twitterからツイートの投稿時間を取得
  • 曜日・時刻ごとに集計
  • ヒートマップにして表示

結果

  • 人によっては明白に寝てる時間が分かる。(社会人はちゃんと夜ちょっと寝ている)
  • 私の寝ている時間もなんとなく分かる。
  • 冬休みを挟んでしまっているので時間割までは分からない。 f:id:matsu7874:20160122131904p:plain

Twitterからtweet時刻の取得

  • GitHub - sixohsix/twitter: Python Twitter APIを使うと簡単。
  • ツイートの投稿時間は'create_at'です。
  • 'user'の'create_at'と間違えないように気をつけます。
  • 1アクセスで200tweet、最大3200tweetまでしか取得できません。ケチ!

集計

  • 時刻がUTCで与えられますので、Asia/Tokyoにします。

可視化

ソースコード

twitter apiの鍵情報はよく使うので以下の形で別ファイルにまとめている。

# twitter_keys.py
KEYS = {'consumer_key': 'xxxxxxxxxxxxxxxxxxxxxxxxx',
        'consumer_secret': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
        'access_token': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
        'access_secret': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        }
import twitter
from twitter_keys import KEYS
import seaborn


days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

t = twitter.Twitter(auth=twitter.OAuth(token=KEYS['access_token'], token_secret=KEYS['access_secret'],
                                       consumer_key=KEYS['consumer_key'], consumer_secret=KEYS['consumer_secret']))

users = ['matsu7874']
for username in users:
    timelog = [[0 for j in range(24)] for i in range(7)]
    total_tweets = 0
    latest_tweet = t.statuses.user_timeline(screen_name=username, count=1)[0]
    max_id = int(latest_tweet['id_str'])
    latest_date = latest_tweet['created_at']
    for i in range(16):
        response = t.statuses.user_timeline(screen_name=username, count=200, max_id=max_id)
        if response == []:
            break
        max_id = int(response[-1]['id_str']) - 1
        oldest_date = response[-1]['created_at']
        for tweet in response:
            s = tweet['created_at'].split()
            day = days.index(s[0])
            h = int(s[3].split(':')[0]) + 9
            if h >= 24:
                h %= 24
                day = (day + 1) % 7
            timelog[day][h] += 1
    for i in range(7):
        print(timelog[i])
        total_tweets += sum(timelog[i])
    seaborn.set()
    ax = seaborn.heatmap(timelog)
    title = str(username) + ' tweet log (n=' + str(total_tweets) +')\n'
    title += 'From ' + oldest_date + '\nTo ' + latest_date
    seaborn.plt.title(title)
    seaborn.plt.ylabel('day')
    seaborn.plt.xlabel('time(Asia/Tokyo)')
    seaborn.plt.yticks(range(7), list(reversed(days)))
    seaborn.plt.savefig(str(username) + '_log.png', dpi=300)

ページング

Working with Timelines | Twitter Developersに書いてあるように、
max_idを直前に処理したツイートのid(_str)-1をmax_idに指定してやれば上手く動きます。

感想

綺麗に真っ白の帯が出る生活がしたい。