理系学生日記

おまえはいつまで学生気分なのか

2023年のミーティング時間をChatGPTで解析してみる

僕は、タイムトラッキングはそれなりに必要なものだと思っています。タイムトラッキングをすることで、自分の時間の使い方を客観的に見ることができます。

私の観察によれば、成果をあげる者は仕事からスタートしない。時間からスタートする。計画からもスタートしない。何に時間がとられているかを明らかにすることからスタートする。 (中略) 重要なことは、記録することである。記憶によってあとで記録するのではなく、ほぼリアルタイムに記録していくことである。

プロフェッショナルの条件――いかに成果をあげ、成長するか

打ち合わせの時間というのは、毎日それなりの時間を必要とします。ではそれがどれだけの時間なのかというのは気になるところです。 僕は毎日の時間の使い方をTaskChute Cloudを用いて記録しています。そして、TaskChute Cloudでは日々の時間をTSVでエクスポートできます。

このTSVを用いて、2023年の打ち合わせの時間をChatGPTで解析してみました。

1日の打ち合わせ時間

では1日あたりの打ち合わせ時間はどの程度でしょうか。1日あたりのミーティング時間を月毎に集計した上で、95%信頼区間、および、その回帰直線を示したのが次のグラフです。

月間の打ち合わせ時間

月間の打ち合わせ時間は次のグラフのようになりました。

大体、月当たり80-100時間程度の打ち合わせ時間があるようです。

打ち合わせの時間とそれに対する考察

グラフを見れば容易に分かる通り、一年を通して徐々に打ち合わせ時間が増加しています。さまざまなプロジェクトへ関わるようになり、それに伴って打ち合わせ時間が増えているということでしょう。

ChatGPTを用いたデータ解析

今回初めてChatGPTを用いてデータを解析しました。 僕自身はTSVからミーティングのデータを抽出するところまでで、他については一切コーディングを行なっていません。僕が書いたのは以下の抽出ワンライナーだけです。

$ cat tasks_*.csv | iconv -futf16le -t utf8 | awk -F"\t" '$7=="MTG" { print $1, $15 }' > mtg.dat

$ head -5 mtg.dat
2023-01-06 00:30
2023-01-06 00:14
2023-01-06 00:16
2023-01-06 00:32
2023-01-10 00:15

上記通り抽出したデータファイルをChatGPTにアップロードし、ChatGPTにグラフを書いてもらいながら、そのグラフを見て「こういう解析を行なってほしい」とか指示をしただけです。ここまで簡単にデータ解析が行えるとは思っていませんでした。

こういうデータの解析・可視化については、今年はより力を入れていかないといけない状況です。 その中で、ChatGPTは非常に有用なツールになりそうです。

ChatGPTのコード

import matplotlib.pyplot as plt
import numpy as np
from collections import defaultdict
from datetime import timedelta
from scipy.stats import linregress

# データを処理する関数
def process_data(data):
    # 日付ごとに時間を合計
    daily_totals = defaultdict(timedelta)
    for line in data:
        try:
            date_str, time_str = line.split()
            hours, minutes = map(int, time_str.split(':'))
            daily_totals[date_str] += timedelta(hours=hours, minutes=minutes)
        except ValueError:
            # 不正な形式の行は無視
            continue

    # 月ごとに日ごとのミーティング時間の平均と標準偏差を計算
    monthly_data = defaultdict(list)
    for date, total in daily_totals.items():
        month = date[:7]  # YYYY-MM
        hours = total.seconds / 3600
        monthly_data[month].append(hours)

    monthly_averages = {}
    for month, hours_list in monthly_data.items():
        average = np.mean(hours_list)
        std_dev = np.std(hours_list)
        n = len(hours_list)
        ci_95 = 1.96 * std_dev / np.sqrt(n)
        monthly_averages[month] = (average, ci_95)

    return monthly_averages

# 回帰直線を計算する関数
def calculate_regression_line(months, averages):
    months_numeric = [int(month.split('-')[1]) for month in months]
    slope, intercept, _, _, _ = linregress(months_numeric, averages)
    regression_line = [slope * x + intercept for x in months_numeric]
    regression_equation = f"y = {slope:.2f}x + {intercept:.2f}"
    return regression_line, regression_equation

# グラフを作成する関数
def create_plot(monthly_averages, output_file_path):
    months = list(monthly_averages.keys())
    averages = [avg for avg, _ in monthly_averages.values()]
    lower_bounds = [avg - ci for avg, ci in monthly_averages.values()]
    upper_bounds = [avg + ci for avg, ci in monthly_averages.values()]

    regression_line, regression_equation = calculate_regression_line(months, averages)

    plt.figure(figsize=(12, 6))
    plt.plot(months, averages, marker='o', label='Monthly Average Hours')
    plt.fill_between(months, lower_bounds, upper_bounds, color='gray', alpha=0.2, label='95% Confidence Interval')
    plt.plot(months, regression_line, color='red', label='Regression Line')
    plt.text(0.05, 0.95, f'Regression Line: {regression_equation}', transform=plt.gca().transAxes, color='red')

    plt.title('Monthly Average Meeting Hours with 95% Confidence Interval and Regression Line')
    plt.xlabel('Month')
    plt.ylabel('Average Hours')
    plt.ylim(bottom=0)
    plt.xticks(rotation=45)
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.savefig(output_file_path)

# データの読み込み
with open('/mnt/data/mtg.dat', 'r') as file:
    data = file.readlines()

# データ処理
monthly_averages = process_data(data)

# グラフ作成と保存
output_file_path_refactored = '/mnt/data/monthly_average_meeting_hours_refactored.png'
create_plot(monthly_averages, output_file_path_refactored)

output_file_path_refactored