Skip to content

7. 時系列データ分析

第 7 回では、時系列データの分析方法について学びます。

時系列データは、時間の経過に沿って収集されたデータです。株価分析や、気象データの予測、販売データの解析、トレンド予測など、さまざまな分野で活用されています。

7.1 時系列データの基本

7.1.1 時系列データの定義

時系列データとは、各データポイントが時間に対応しているデータのことであり、主に以下の特徴を持ちます。

  • データが時間軸に沿って配置されている。
  • データが連続的または離散的(定期的)に収集されている。
  • 過去のデータが未来のデータに影響を与えることがある。

7.1.2 時系列データ分析の目的

時系列データは多くの分野で使用されており、その主要な分析目的としては以下のようなものがあります。

  • 過去のパターンの理解
  • 将来の値の予測
  • 異常値の検出
  • トレンドや周期性の把握

7.2 pandas による時系列データの基本

時系列データ処理には、主に pandas と numpy ライブラリを使用します。

7.2.1 時系列データの生成

日付範囲のデータを生成するには、pandas.date_range() 関数を使用し、引数で開始日 (start) やデータ数 (periods)、頻度 (freq) などを指定します。

import pandas as pd
import numpy as np

# データ数
n = 7

# 日付範囲の生成
date_range = pd.date_range(start="2026-06-03", periods=n, freq="D")

# 時系列データの生成
data = np.random.randn(n)  # ランダムなデータ生成
ts = pd.Series(data, index=date_range)

# 時系列データの表示
print(ts)
Output
2026-06-03   -0.957430
2026-06-04   -0.519095
2026-06-05    0.429354
2026-06-06   -0.982983
2026-06-07   -0.704216
2026-06-08    0.185925
2026-06-09   -1.301902
Freq: D, dtype: float64

頻度パラメータについて

pandas.date_range() 関数の頻度 (freq) は、デフォルトで D (1 日毎) が指定されていますが、以下のようにさまざま変更することができます。

# 毎週金曜日(W-FRI)
pd.date_range(start="2026-06-03", periods=4, freq="W-FRI")

# 3日毎
pd.date_range(start="2026-06-03", periods=10, freq="3D")

# 2時間毎
pd.date_range(start="2026-06-03", periods=12, freq="2h")

その他の頻度パラメータの詳細については、こちら (Offset aliases) を確認するようにしてください。

7.2.2 CSV ファイルから時系列データの作成

CSV ファイルから時系列データを作成する方法を見ていきましょう。ここでは、CHIKUWA Editor の利用ログ(後述の「活動ログデータ」)を例に進めます。このログには、以下のように日別の「作業時間」「打鍵数」「実行回数」などの時系列情報が含まれています。

活動ログデータ (chikuwa-stats-2026-05-30.csv)
日付,作業時間(秒),作業時間(分),打鍵数,実行回数,保存回数,エラー回数
2026-03-27,3925,65,128,44,51,3
2026-03-28,3774,63,710,62,80,14
2026-03-29,3245,54,334,39,47,8
2026-03-30,4312,72,205,16,18,1
2026-03-31,2596,43,170,60,64,7
...

これを DataFrame として読み込むには、以前にも紹介したように、pandas.read_csv() 関数を用います。しかし、そのままでは先頭の日付の列 (日付) が文字列として認識されてしまい、時系列データとして扱うことができません。このような場合、以下のような手順で時系列データに変換します。

  1. pandas.to_datetime() 関数で日付の列を datetime 型に変換
  2. DataFrame.set_index() 関数で日付の列を DataFrame のインデックスに設定

実際のコード例は以下のようになります。

import pandas as pd

# CSV ファイルの読み込み
df = pd.read_csv("chikuwa-stats-2026-05-30.csv")

# 時系列データに変換
df["日付"] = pd.to_datetime(df["日付"])

# インデックスを日付に設定
df = df.set_index("日付")

# 先頭行の表示
print(df.head())
Output
            作業時間(秒)  作業時間(分)  打鍵数  実行回数  保存回数  エラー回数
日付
2026-03-27     3925      65   128    44    51      3
2026-03-28     3774      63   710    62    80     14
2026-03-29     3245      54   334    39    47      8
2026-03-30     4312      72   205    16    18      1
2026-03-31     2596      43   170    60    64      7

CSV の読込と同時に時系列データ作成

はじめから CSV のどの列が日時を表すかわかっている場合は、pandas.read_csv() 関数の引数で parse_dates=["列名"] を指定することで、特定の列を自動的に datetime 型に変換したうえで読み込みます。以下は、日付 列を datetime 型として読み込む例です。

CSV 読込時に時系列データ作成
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"])

さらに、インデックスを 日付 列にしたい場合は、以下のように index_col を指定します。

CSV 読込時に時系列データ作成 & インデックス設定
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

Note

データが日付順になっていない場合は、DataFrame.sort_index() 関数で並び替えることができます。このとき、引数で ascending=False を指定すると、降順に並び替えることができます。

7.2.3 データの選択とスライシング

通常の DataFrame と同様に、DataFrame.loc インデクサを用いることで、時系列データから特定の日時の選択や、スライシングを行うことができます。

# 特定の日付を選択
print(df.loc["2026-05-11"])

# 特定の日付範囲を抽出(スライシング)
print(df.loc["2026-05-11":"2026-05-18"])
Output
作業時間(秒)    2568
作業時間(分)      43
打鍵数         622
実行回数         54
保存回数         57
エラー回数          6
Name: 2026-05-11 00:00:00, dtype: int64
            作業時間(秒)  作業時間(分)  打鍵数  実行回数  保存回数  エラー回数
日付
2026-05-11     2568      43   622    54    57      6
2026-05-12       30       1    71     8     8      1
2026-05-13      377       6    38    19    19      6
2026-05-15      391       7    70    17    17      2
2026-05-16        6       0    18     2     2      0
2026-05-17     1318      22   163    32    44      4
2026-05-18     2629      44   823    88    92      8

歯抜けの日付について

このログは利用があった日のみが記録されているため、日付が連続していません(例えば 2026-05-13 の次が 2026-05-15 で、2026-05-14 は存在しません)。このように欠けた日付を補完したい場合は、後述の「7.5.1 リサンプリング」を用いて頻度を D(1 日毎)にそろえることができます。

7.3 日付と時間のデータ型と変換

時系列データを正しく扱うために、日付と時間を適切に扱うための方法を学びましょう。

7.3.1 日付と時間のデータ型

Python で日付と時間の効率的に取り扱うためには、datetime モジュールを使います。このモジュールに含まれる datetime クラスは、日付と時間の両方を扱うことができます。

datetime モジュールから datetime クラスをインポートするには、以下のようにします。

from datetime import datetime

datetime.now() 関数を用いると、現在の日時を取得することができます。

現在日時の取得
from datetime import datetime

now = datetime.now()
print("現在の日時: ", now)
Output
現在の日時:  2026-05-30 05:14:52.577857

datetime クラスの他にも、日付のみを扱う date クラスや、時間のみを扱う time クラスも用意されています。

7.3.2 文字列から datetime への変換

文字列を datetime 型(datetime クラスのオブジェクト)に変換するには、strptime() 関数を用います。

文字列から datetime への変換
from datetime import datetime

date_string = "2026-05-30 14:30:00"
dt = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
print("変換された日時: ", dt)
Output
変換された日時:  2026-05-30 14:30:00

ただし、pandas を使用している場合、基本的には pandas.to_datetime() 関数を使用したほうが柔軟性が高く便利です。

7.3.3 datetime から文字列への変換

datetime 型のオブジェクトを文字列に変換するには、strftime() 関数を用います。このとき、引数で書式コードを指定することで、変換後の日時表記のスタイルを調整することができます。

datetime から文字列への変換
from datetime import datetime

# 現在日時の取得
now = datetime.now()

# datetime を文字列に変換
formatted_date = now.strftime("%Y年%m月%d日 %H時%M分%S秒")

print("フォーマット前の日時:" , now)
print("フォーマット後の日時:" , formatted_date)
Output
フォーマット前の日時: 2026-05-30 05:39:52.731397
フォーマット後の日時: 2026年05月30日 05時39分52秒

書式の詳細は、Python 公式ドキュメントの「strftime() と strptime() の書式コード」を参照するようにしてください。

7.3.4 タイムゾーンの取り扱い

datetime 型のオブジェクトは、デフォルトではタイムゾーンの情報を含みません (naive datetime)。

datetime モジュールで任意のタイムゾーンを設定するには、zoneinfo モジュールを用います。例えば、タイムゾーンを JST (日本時間, UTC+0900) にするには、以下のようにします。

from datetime import datetime
from zoneinfo import ZoneInfo

# 現在日時の取得(タイムゾーン: JST)
now = datetime.now(ZoneInfo("Asia/Tokyo"))
print(now)
Output
2026-05-30 14:49:41.189614+09:00

pandas でタイムゾーンを設定するには、DataFrame.tz_localize() 関数を用います。タイムゾーンを JST にするには、引数で "Asia/Tokyo" を指定します。以下は、日時の文字列を datetime に変換し、インデックスに設定したうえで、タイムゾーンを JST にするコードの例です。

title
import pandas as pd

# CSV の読み込み & 時系列データに変換 (index = naive timezone)
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# タイムゾーンを JST に設定
df.index = df.index.tz_localize("Asia/Tokyo")
print(df.index[0])
Output
2026-03-27 00:00:00+09:00

また、既に設定されているタイムゾーンを別のタイムゾーンに変換するには、DataFrame.tz_convert() 関数を用います。

7.4 時系列データの可視化

時系列データを可視化する方法を見ていきましょう。

7.4.1 Matplotlib による時系列データ可視化

時系列データはこれまで学んできた方法と同様、Matplotlib や Seaborn で可視化することができます。Matplotlib による基本的な折れ線グラフを描くには、以下のように pyplot.plot() 関数を用います。

import pandas as pd
import matplotlib.pyplot as plt

# CSV の読み込み & 時系列データに変換
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 折れ線グラフで可視化
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(df["作業時間(秒)"])
ax.set_ylabel("作業時間(秒)")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

Matplotlibによる時系列データ可視化

7.4.2 Matplotlib による時系列データの軸調整

前項では pyplot.plot() 関数による時系列データの可視化を行いましたが、日付軸のフォーマットや、軸の間隔を調整することで、より見やすいグラフにすることができます。

日付軸のフォーマット設定には、matplotlib.dates モジュールに含まれる dates.DateFormatter や dates.DayLocator が役に立ちます。例えば、ax という名前の Axes オブジェクトがあるとき、これらは以下のようにして使うことができます。

import matplotlib.dates as mdates

# x軸の日付を「2026/05/11」→「05/11」のようにフォーマット
ax.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))

# x軸の日付の間隔を3日毎に設定
ax.xaxis.set_major_locator(mdates.DayLocator(interval=3))

時間軸のフォーマット

日付の軸ラベルが「5/11」のようにシンプルになり、3 日毎に配置されるようになりました。

プログラムは少しややこしく感じられるかもしれませんが、はじめのうちはこういうものであると思い、フォーマット指定部分や数字の部分のみを変更するくらいでも問題ありません。以下は、上記コードのフォーマット設定を構成する要素の概説です。

7.4.3 複合グラフの描画

Matplotlib を使用して、複合グラフを描いてみましょう。複合グラフとは、複数の異なる種類のグラフを組み合わせて描画するグラフのことで、例えば「折れ線グラフ」と「棒グラフ」を組み合わせたものなどです。

試しに、これまでの方法を組み合わせて折れ線グラフを棒グラフを同時に描いてみましょう。以下のコード例では、折れ線グラフに 作業時間(秒) を、棒グラフに 打鍵数 を指定しています。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 図と左y軸を作成
fig, ax = plt.subplots(figsize=(10, 4))

# 折れ線グラフ: 作業時間(秒)
ax.plot(
    df.index,
    df["作業時間(秒)"],
    color="royalblue",
    marker="o",
    label="作業時間(秒)"
)
ax.set_ylabel("作業時間(秒)")

# 棒グラフ: 打鍵数
ax.bar(
    df.index,
    df["打鍵数"],
    color="red",
    alpha=0.4,
    label="打鍵数"
)
ax.set_ylabel("打鍵数")

# x軸フォーマットと間隔
ax.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=3))

# レイアウト調整・表示
plt.xticks(rotation=45)
fig.tight_layout()
plt.show()

簡易的な複合グラフ

折れ線グラフと棒グラフを同時に表示することができました。しかし、2 つのグラフの軸が共有されているため、数値のスケールが合っておらず、棒グラフ(打鍵数)の様子が見えにくくなってしまっています。このようなときは、グラフの左側と右側で、それぞれ異なるスケールの軸を設定することが望ましいです。

x 軸を共有して、y 軸を別に作成するためには、Axes.twinx() 関数を用います。そうすることで、以下のように、スケールが異なっていても視覚的にわかりやすい複合グラフを作成することができます。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 図と左y軸を作成
fig, ax1 = plt.subplots(figsize=(10, 4))

# 折れ線グラフ: 作業時間(秒)
line = ax1.plot(
    df.index,
    df["作業時間(秒)"],
    color="royalblue",
    marker="o",
    label="作業時間(秒)"
)
ax1.set_ylabel("作業時間(秒)")
ax1.set_ylim(0)

# 右y軸を作成
ax2 = ax1.twinx()

# 棒グラフ: 打鍵数
bar = ax2.bar(
    df.index,
    df["打鍵数"],
    color="red",
    alpha=0.4,
    label="打鍵数"
)
ax2.set_ylabel("打鍵数(回)")

# x軸フォーマットと間隔
ax1.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
ax1.xaxis.set_major_locator(mdates.DayLocator(interval=3))

# 凡例をまとめて表示(折れ線とバー両方)
ax1.legend([line[0], bar], ["作業時間(秒)", "打鍵数(回)"], loc="upper left")

# レイアウト調整・表示
plt.xticks(rotation=45)
fig.tight_layout()
plt.show()

調整後の複合グラフ

複数の凡例をまとめて表示

ここでは折れ線グラフを line、棒グラフを bar という変数に格納しており、Axes.legend() 関数にラベル情報を併せてリストで渡すことで、複数の凡例をまとめて表示させています。なお、pyplot.plot() 関数はリストを返すため、line には [0] をつけて先頭のデータを渡しています。

7.5 時系列データの前処理

本章の最後に、時系列データに対する重要な前処理のテクニックを幾つか見ていきましょう。

7.5.1 リサンプリング

リサンプリングとは、時系列データの頻度(間隔)を変換する操作のことです。高頻度のデータを低頻度に変換することを ダウンサンプリング、低頻度のデータを高頻度に変換することを アップサンプリング と呼びます。

ダウンサンプリング

ダウンサンプリングでは、一般的にデータを集約することで、頻度を減らします。例えば、1 日単位のデータを 1 週間単位に変換する場合、DataFrame.resample() 関数を用いて以下のように書きます。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 一週間単位のデータを集約(平均化)
resampled = df.resample("7D").mean()

# 図と左y軸を作成
fig, ax = plt.subplots(figsize=(10, 4))

# 折れ線グラフ: 作業時間(秒)
ax.plot(
    resampled.index,
    resampled["作業時間(秒)"],
    color="royalblue",
    marker="o",
    label="作業時間(秒)"
)
ax.set_ylabel("作業時間(秒)")
ax.set_ylim(0)

# x軸フォーマットと間隔
ax.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=3))

# レイアウト調整・表示
plt.xticks(rotation=45)
fig.tight_layout()
plt.show()

ダウンサンプリング

時系列データの大局的な変動を表すグラフになりました。ダウンサンプリングの集約処理としては、主に以下の関数が用いられます。

  • mean(): 平均値を計算
  • sum(): 合計値を計算
  • min(): 最小値を計算
  • max(): 最大値を計算

アップサンプリング

アップサンプリングでは、新たにデータポイントを補完して、データの頻度を増やします。DataFrame.resample("[freq]").asfreq() とすることで、指定した頻度 (freq) のデータポイントが追加され、NaN で補完されます。

今回のログは利用があった日のみが記録されており、日付が歯抜けになっています。resample("D").asfreq() で頻度を D(1 日毎)にそろえると、抜けていた日付が NaN として追加され、日付の間隔がそろいます。

import pandas as pd

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 1日毎の頻度にそろえる(抜けていた日付が NaN で追加される)
upsampled = df["作業時間(秒)"].resample("D").asfreq()
print(upsampled.head(8))
Output
日付
2026-03-27    3925.0
2026-03-28    3774.0
2026-03-29    3245.0
2026-03-30    4312.0
2026-03-31    2596.0
2026-04-01       NaN
2026-04-02       NaN
2026-04-03       NaN
Freq: D, Name: 作業時間(秒), dtype: float64

2026-04-01 から 2026-04-03 のように、元データに存在しなかった日付が追加され、値が NaN になっていることがわかります。このような欠損値を処理するには、DataFrame.fillna() 関数を用います。例えば「利用がなかった日は作業時間 0」とみなすなら、fillna(0) で 0 に置き換えます。

# 欠損値を 0 で補完
filled = upsampled.fillna(0)
print(filled.head(8))
Output
日付
2026-03-27    3925.0
2026-03-28    3774.0
2026-03-29    3245.0
2026-03-30    4312.0
2026-03-31    2596.0
2026-04-01       0.0
2026-04-02       0.0
2026-04-03       0.0
Freq: D, Name: 作業時間(秒), dtype: float64

さまざまな欠損値の補完方法

DataFrame.fillna() 関数に値を渡すと、その値で欠損を埋めます。このほか、直前の値で埋める DataFrame.ffill()(前方補完)や、直後の値で埋める DataFrame.bfill()(後方補完)、前後の値から補間する DataFrame.interpolate()(補間)などがあり、データの性質に応じて使い分けます。

7.5.2 移動平均

移動平均 (moving average) とは、一定の区間(窓, window)ごとに平均をとりながら、その窓を 1 つずつずらして計算していく手法です。日々の細かな変動(ノイズ)をならし、全体的なトレンドを見やすくする効果があります。

移動平均を計算するには、Series.rolling() 関数で窓の幅 (window) を指定し、続けて mean() などの集約関数を呼び出します。以下は、作業時間(秒) の 3 点移動平均を計算する例です。

import pandas as pd

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 3点移動平均を計算
rolling = df["作業時間(秒)"].rolling(window=3).mean()
print(rolling.head(8))
Output
日付
2026-03-27            NaN
2026-03-28            NaN
2026-03-29    3648.000000
2026-03-30    3777.000000
2026-03-31    3384.333333
2026-04-05    2314.000000
2026-04-06     948.000000
2026-04-08     548.666667
Name: 作業時間(秒), dtype: float64

窓の幅が 3 の場合、最初の 2 点は平均をとるためのデータが揃わないため NaN になります。window の値を大きくするほど、より滑らかな(なだらかな)曲線になります。

実際に、元のデータと移動平均を重ねて描いてみましょう。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 3点移動平均を計算
rolling = df["作業時間(秒)"].rolling(window=3).mean()

# 図と軸を作成
fig, ax = plt.subplots(figsize=(10, 4))

# 元データ(薄い折れ線)
ax.plot(df.index, df["作業時間(秒)"], color="gray", alpha=0.5, marker="o", label="元データ")

# 移動平均(強調した折れ線)
ax.plot(rolling.index, rolling, color="royalblue", marker="o", label="3点移動平均")

ax.set_ylabel("作業時間(秒)")
ax.set_ylim(0)
ax.legend()

# x軸フォーマットと間隔
ax.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=3))

# レイアウト調整・表示
plt.xticks(rotation=45)
fig.tight_layout()
plt.show()

移動平均

元データの激しい上下動がならされ、全体的な傾向がつかみやすくなりました。

移動平均の窓と歯抜けの日付

Series.rolling() の window=3 は「直近 3 行分」を意味し、「3 日分」ではない点に注意してください。今回のログのように日付が歯抜けになっている場合、「直近 3 日」で平均をとりたいときは、先にリサンプリング(resample("D"))で日付の間隔をそろえてから移動平均を計算することが望ましいです。なお、window="3D" のように期間を指定する方法もあります。

7.5.3 差分と変化率

時系列データでは、「前の時点からどれだけ増減したか」に注目すると、変化のタイミングや勢いが見えてきます。

直前の値との 差分 を求めるには Series.diff() 関数を用います。

import pandas as pd

# CSV読み込み & 日付をインデックスに
df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 直前の値との差分
print(df["作業時間(秒)"].diff().head())
Output
日付
2026-03-27       NaN
2026-03-28    -151.0
2026-03-29    -529.0
2026-03-30    1067.0
2026-03-31   -1716.0
Name: 作業時間(秒), dtype: float64

最初の行は比較対象がないため NaN になります。値が正なら前回より増加、負なら減少していることを表します。

また、直前の値からの 変化率(増減の割合)を求めるには Series.pct_change() 関数を用います。

# 直前の値からの変化率
print(df["作業時間(秒)"].pct_change().head())
Output
日付
2026-03-27         NaN
2026-03-28   -0.038471
2026-03-29   -0.140170
2026-03-30    0.328814
2026-03-31   -0.397959
Name: 作業時間(秒), dtype: float64

例えば 2026-03-31 の -0.397959 は「前回より約 40% 減少した」ことを意味します。100 を掛ければパーセント表記になります。

このほか、値を先頭から積み上げていく累積和を求める Series.cumsum() 関数もあり、「これまでの合計作業時間の推移」などを見るのに便利です。

差分・変化率と歯抜けの日付

Series.diff() や Series.pct_change() は移動平均と同様、「直前の行」との比較であり、「前の日との比較」ではありません。歯抜けの日付をまたいで「前日比」を求めたい場合は、先に resample("D") で日付の間隔をそろえてから計算しましょう。

その他の時系列データ分析

本講義では取り扱いませんが、時系列データを分析するうえで重要なキーワードとして、「トレンド抽出」「季節性抽出」「自己回帰」「ラグプロット」などがあります。高度な分析に興味のある人は、これらのキーワードを参考に調べてみてください。

演習

演習用データの準備

以下の演習では、活動ログデータの CSV ファイルを使用します。CHIKUWA Editor を使用している場合は、「学習統計」から自身の「作業時間(全期間)の CSV」をダウンロードして使用してください。CHIKUWA Editor を使用しておらず自身のログをダウンロードできない場合は、サンプルとして chikuwa-stats-2026-05-30.csv(加納のログ)をダウンロードし、活用してください。

演習 7-1(初級):実行回数とエラー回数の可視化

活動ログデータの CSV ファイルを読み込み、日付をインデックスにした時系列データに変換したうえで、次の処理を行ってください。

  1. 「実行回数」と「エラー回数」の折れ線を 1 つのグラフに重ねて描く
  2. 凡例(legend)を表示する
テンプレートコード
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

fig, ax = plt.subplots(figsize=(10, 4))

# 1. 「実行回数」と「エラー回数」の折れ線を重ねて描く

# 2. 凡例を表示

plt.tight_layout()
plt.show()

演習 7-2(初級):月ごと・週ごとの作業時間の集計

活動ログデータの CSV ファイルを読み込み、日付をインデックスにした時系列データに変換したうえで、次の処理を行ってください。

  1. resample を使って、月ごと("ME")の「作業時間(分)」の合計を求める
  2. resample を使って、週ごと("W")の「作業時間(分)」の平均を求める
  3. それぞれの結果を表示する
テンプレートコード
import pandas as pd

df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 1. 月ごと("ME")に「作業時間(分)」を合計

# 2. 週ごと("W")に「作業時間(分)」を平均

# 3. それぞれの結果を表示

演習 7-3(中級):曜日別の作業時間

活動ログデータの CSV ファイルを読み込み、日付をインデックスにした時系列データに変換したうえで、次の処理を行ってください。

  1. 日付から曜日を求めて、新しい列(例: weekday)に格納する(df.index.day_name() を使う)
  2. 曜日ごとの「作業時間(秒)」の平均を groupby で計算する
  3. 月曜→日曜の順に並べ替える(reindex を使う)
  4. 計算した平均を棒グラフで可視化する
テンプレートコード
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 1. 曜日の列を作成(df.index.day_name())

# 2. 曜日ごとの「作業時間(秒)」の平均を計算

# 3. 月曜→日曜の順に並べ替え
order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

# 4. 棒グラフで可視化
fig, ax = plt.subplots(figsize=(10, 4))

plt.tight_layout()
plt.show()

演習 7-4(中級):エラー率の可視化

活動ログデータの CSV ファイルを読み込み、日付をインデックスにした時系列データに変換したうえで、次の処理を行ってください。

  1. 「エラー回数 ÷ 実行回数」でエラー率を計算する
  2. 実行回数が 0 の日に生じる inf / NaN を処理する(除外または補完)
  3. エラー率の変化を折れ線グラフで可視化する
テンプレートコード
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv("chikuwa-stats-2026-05-30.csv", parse_dates=["日付"], index_col="日付")

# 1. エラー率(エラー回数 ÷ 実行回数)を計算

# 2. inf / NaN を処理(実行回数が 0 の日に発生)

# 3. 折れ線グラフで可視化
fig, ax = plt.subplots(figsize=(10, 4))

plt.tight_layout()
plt.show()