【python】睡眠時間管理するプログラム作った話

この記事は Aizu Advent Calendar 2017 の11日目の記事です

あぶすとらくと

pythonを使って日々の睡眠時間と起床時間を記録してグラフ化するシステムを作ってみたよ!

なぜ作ったの?

理由としては、

  • ここ数ヶ月ぐらい3時から4時就寝の生活が続いており、睡眠時間が死んでるのと単位がやばいので何とかしないとと思っていた

  • 睡眠時間を見える化して自分にプレッシャーを与えると結構いいらしい

  • 自分の使ってる睡眠管理アプリが2度寝した時に正確に記録できない

ということでじゃ自分で睡眠時間を記録できるもの作っちゃおうと思い立ち作ってみました

機能

具体的にはこんな機能を作成します

  • 標準入力からその日の就寝時間と起床時間を受け取る

  • 「8時30分」や「0:30」などどんなフォーマットで入力が来ても時間を取得できるようにする

  • 取得した就寝時間と起床時間を日付とともにcsvファイルに記録する

  • csvファイルから就寝時間と起床時間の推移をグラフイメージにプロットする

使ったもの

環境

開発言語

主なライブラリ

  • datetime (日付と時間のデータを扱うため)

  • pandas (データのcsvファイルへの読み書き)

  • matplotlib (グラフイメージ作成)

など

準備

pipでpandas,matplotlibライブラリをインストールしておく

実装

入力から時間を取得する関数

import re

ERROR = 0

# テキストから時間を抽出
def get_time(text):
    m = re.findall('[\d]+', text)
    if len(m) == 2:
        return m;

    return [ERROR,'何時かわかんないよ〜\nもう一度入力し直してね']

正規表現を使って文字列から数字を抽出します

import re正規表現を使うモジュールを読み込み、文字列の中のパターンとマッチする部分をすべてリストとして返すfindall関数を呼びます

引数[\d]+textから1つ以上の連続した数字を検出します

時、分をリストの要素として受け取るため、取得したリストの長さが2以外ならエラーを返します

csvファイルに日付、就寝時間、起床時間を記録する関数

import os
import pandas as pd
from datetime import date

CSV_PATH = "./timedata.csv"
today = date.today()

# csvファイルに時間を記録
def write_csv(sleep_time, wakeup_time):
    
    if not os.path.exists(CSV_PATH):
        # データフレームを作成
        df = pd.DataFrame(
            [[today, sleep_time, wakeup_time]],
            columns=['Date', 'Sleep_Time', 'Wake_Up_time']
            )
        df.to_csv(CSV_PATH, index=False, encoding="utf-8")
    else:
        w = pd.DataFrame([[today, sleep_time, wakeup_time]])
        w.to_csv(CSV_PATH, index=False, encoding="utf-8", mode='a', header=False)

最初にdatetimeモジュールのdate.today()で記録日の日付を取得しておきます

csvファイルが存在していない場合は新規作成します

その場合、データフレームを作成し、列のindexとして日付(Date)、就寝時間(Sleep_Time)、起床時間(Wake_Up_time)を指定し、to_csv関数でデータフレームをcsvファイルとして書き込みます

既にcsvファイルがあれば、データフレームに取得した日付、就寝時間、起床時間のデータを入れ、csvファイルに追記します

追記する場合はオプションでmode='a' header=Falseを追加します

csvファイルからグラフイメージを作成する関数

import pandas as pd
import matplotlib.pyplot as plt

CSV_PATH = "./timedata.csv"

# グラフイメージをプロット
def plot_graph():
    csv = pd.read_csv(CSV_PATH)
    plt.plot(csv.Date, csv.Sleep_Time, label='sleep time')
    plt.plot(csv.Date, csv.Wake_Up_time, label='wake up time')

    plt.legend()
    plt.savefig("./graph.png")

read_csv関数でcsvファイルをデータフレームとして読み込み、plot関数のx軸に日付、y軸に就寝時間と起床時間を指定し、分かりやすいように凡例名(label)を指定しました

余談ですが、このplot関数に日付を入れる時にdatetimeオブジェクトを作成して指定するとなぜか日付が小数値で出力されるという現象が起こり、半日ぐらいハマってました...

最終的にcsvの日付をとりあえず突っ込んでみたらちゃんと表示されてるし、なぜだろう...

話を戻して、次のlegend関数でグラフの凡例をつけています

最後にsavefig関数でグラフイメージを保存します

全体の実装

import os
from datetime import date
import datetime
import re
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

CSV_PATH = "./timedata.csv"
ERROR = 0

today = date.today()


# csvファイルに時間を記録
def write_csv(sleep_time, wakeup_time):
    
    if not os.path.exists(CSV_PATH):
        # データフレームを作成
        df = pd.DataFrame(
            [[today, sleep_time, wakeup_time]],
            columns=['Date', 'Sleep_Time', 'Wake_Up_time']
            )
        df.to_csv(CSV_PATH, index=False, encoding="utf-8")
    else:
        w = pd.DataFrame([[today, sleep_time, wakeup_time]])
        w.to_csv(CSV_PATH, index=False, encoding="utf-8", mode='a', header=False)


# テキストから時間を抽出
def get_time(text):
    m = re.findall('[\d]+', text)
    if len(m) == 2:
        return m;

    return [ERROR,'何時かわかんないよ〜\nもう一度入力し直してね']


# グラフイメージをプロット
def plot_graph():
    csv = pd.read_csv(CSV_PATH)
    plt.plot(csv.Date, csv.Sleep_Time, label='sleep time')
    plt.plot(csv.Date, csv.Wake_Up_time, label='wake up time')

    plt.legend()
    plt.savefig("./graph.png")


if __name__ == '__main__':
    
    count = 0
    sleep_time = datetime.datetime.now()
    wakeup_time = datetime.datetime.now()

    while count < 2:
        if count == 0:
            print('昨日の就寝時間を入力してください')
            input_str = str(input())
            time = get_time(input_str)
        else:
            print('今日の起床時間を入力してください')
            input_str = str(input())
            time = get_time(input_str)

        if not time[0]:
            print(time[1])
            continue

        #時間を整形
        if len(time[0]) == 1:
            time[0] = '0' + time[0]
        if len(time[1]) == 1:
            time[1] = '0' + time[1]

        if count == 0:
            str_time = time[0] + ':' + time[1] + ':00'
            sleep_time = datetime.datetime.strptime(str_time, '%H:%M:%S')
            sleep_time = sleep_time.time()
        else:
            str_time = time[0] + ':' + time[1] + ':00'
            wakeup_time = datetime.datetime.strptime(str_time, '%H:%M:%S')
            wakeup_time = wakeup_time.time()
    
        count+=1
    
    write_csv(sleep_time, wakeup_time)
    plot_graph()

全体として上記のような実装になっています

mainのコードでは主に就寝時間と起床時間の入力を施し、時間を取得してフォーマットを整形ののちcsvファイルにデータを保存する関数とグラフイメージを作成する関数を呼ぶという流れになっています

結果

Date Sleep_Time Wake_Up_time
2017-12-04 03:27:00 09:10:00
2017-12-05 02:44:00 08:24:00
2017-12-06 03:48:00 09:14:00
2017-12-07 04:44:00 09:55:00

f:id:sansuke05:20171207143314p:plain

現状ひどいですね...😅😅

おわりに

pandasやmatplotlibはデータ解析用のライブラリで今回は触りぐらいしか使ってませんが、調べてみるとかなり奥が深かったです

現状のプログラムだと多分飽きて使わなくなるだろうと思うので、現在開発中のTwitter Botからリプがくるようにするようなシステムを考案中です

カムバック!!朝型生活!!

参考にしたサイト

qiita.com

qiita.com

qiita.com