マガジン

Jupyter Notebookで分析を再現できる形にする:最低限そろえる7つのルール

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

手順を書き留めたノートとデータ用紙、鉛筆が置かれた机
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

結論から言うと、ノートブックを再現できる形にするために最低限必要なのは次の7つです。 1. 冒頭に目的・データ・実行方法を書く 2. 上から順に実行して動く状態にする(保存前に再起動して全セル実行) 3. データの置き場所を相対パスで1か所に決める 4. ライブラリの版を書き出す 5. 乱数の種(シード)を1か所で決めて記録する 6. 加工はすべてコードで行い、途中で件数を確認する 7. 結果の数値を控え、再実行後に突き合わせる この記事では、7ルールを実際に使えるひな形セルと確認表にしました。なお、記事内のコードと数値は説明用の例で、この記事の作成中に実行して確認したものではありません。ご自身の環境で一度動かしてから使ってください。

この記事の目次
  1. 再現できないノートブックは、たいてい「状態」が原因
  2. ルール1・2:冒頭の説明と、実行順序を固定する
  3. ルール3〜5:データ・ライブラリ・乱数を記録する
  4. ルール6・7:加工をコードに残し、結果を突き合わせる
  5. AIに任せる範囲と、人が確認する範囲
  6. 公開前チェックリスト

再現できないノートブックは、たいてい「状態」が原因

Jupyterのノートブックは、コード・説明文・図表を1つの文書にまとめたものです(Project Jupyterのドキュメントによる説明)。コードを実行するのはカーネルという別プロセスで(Jupyter公式のカーネルの説明)、開いている間は変数などの状態がカーネル側に残ります。

そのため、セルを上から順に実行していなくても、画面上は結果が出ます。途中のセルを消したり、下のセルを先に動かしたりすると、いまのカーネルにだけ存在する変数に依存したノートブックができあがります。別の日、別のPCで開くと動かない原因の多くはこれです。後述のルール2〜5は、この「見えない状態」を減らすためのものです。

ルール1・2:冒頭の説明と、実行順序を固定する

ルール1:最初のMarkdownセルに書くこと

最初のセルには、次の項目を書きます。

  • 目的(何を知るための分析か)
  • 使うデータのファイル名と取得日
  • 作成者と最終実行日
  • 実行方法(例:「カーネルを再起動して全セルを上から実行」)
  • 主な結果の数値(ルール7で使います)

ルール2:保存・共有の前に「再起動して全セル実行」

共有や提出の前に、カーネルを再起動してから全セルを上から実行します。メニュー名はJupyterLabやNotebookの版で表記が違うため、「Restart」と「Run All」に当たる項目を探してください。エラーなく最後まで通れば、実行順序に関する問題の大半は消えます。

運用上の目安は次のとおりです。

  • 通らなかったセルは、先に定義すべき変数が下にある場合が多いので、並べ替える
  • 「あとで消すつもり」のセルは、消すか、Markdownで理由を書く
  • 実行回数の番号が飛んでいる出力は、古い結果が残っている可能性があるので、全実行で作り直す

ルール3〜5:データ・ライブラリ・乱数を記録する

ルール3:データの置き場所

フォルダ構成は、たとえば次のように決めます(説明用の例です)。

project/
├ analysis.ipynb
├ data/raw/        # 元データ。上書きしない
├ data/processed/  # コードで作った加工後データ
└ outputs/         # 図・表・環境情報

パスは C:\Users\... のような絶対パスではなく、ノートブックからの相対パスにして、設定セルに1か所だけ書きます。元データを手で編集して保存し直すと、何をしたのか誰にも追えなくなります。元データは触らず、加工はコードで行います。

ルール4:ライブラリの版

pandasには、OSや関連パッケージの版を表示する pandas.show_versions() があり、as_json にファイルパスを渡すとJSONで書き出せます(pandas公式リファレンス)。ただし、表示内容は環境により異なるため、分析で使う主要パッケージは自分でも明示的に書き出しておくと確実です。

ルール5:乱数の記録

scikit-learnの公式ガイドでは、random_state に整数を渡すと、同じデータと環境で呼び出しごとに同じ結果を得やすく、None や RandomState インスタンスを渡すと乱数の状態に応じて結果が変わりうると説明されています。整数を渡す方法は、呼び出しごとに同じ乱数列から始まるため、交差検証などで繰り返し使う場合には、各呼び出しが独立した乱数状態を使う方法とは挙動が異なる点に注意が必要です。RandomState インスタンスは呼び出しで状態が進み、複数の処理で共有すると結果が呼び出し順に影響されます。公式ガイドは、この違いを理解したうえで、推定器やデータ分割に整数またはインスタンスを渡す方法を選ぶよう説明しています(scikit-learn公式ガイド: Controlling randomness)。

したがって、ここでは分割にも推定器にも整数シードを渡す方法を基本例にします。セルの実行順を固定することに加え、データと環境も記録してください。

ひな形セル(説明用の例・未実行)

次の2つのセルを、ノートブックの冒頭に置きます。sales_2026q3.csv や件数は仮の値なので、自分のデータに置き換えてください。

python
# セル1: 設定(パスとシードはここだけに書く)
from pathlib import Path
import hashlib, json, platform
from importlib.metadata import version
import numpy as np
import pandas as pd

SEED = 20261027                      # 分割用の整数シード
RAW = Path("data/raw/sales_2026q3.csv")
OUT = Path("outputs"); OUT.mkdir(exist_ok=True)
rng = np.random.RandomState(SEED)    # 必要な処理で使う場合の乱数生成器

# 環境の記録
env = {"python": platform.python_version(),
       **{p: version(p) for p in ["pandas", "numpy", "scikit-learn"]}}
(OUT / "env.json").write_text(json.dumps(env, indent=2))
print(env)
python
# セル2: データ読み込みと確認
sha = hashlib.sha256(RAW.read_bytes()).hexdigest()
print("sha256:", sha[:12])           # この値を冒頭のMarkdownに控える

df = pd.read_csv(RAW)
EXPECTED_SHAPE = (1200, 8)           # 仮の値。初回実行後に自分の値へ
assert df.shape == EXPECTED_SHAPE, f"件数が違います: {df.shape}"

from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2, random_state=SEED)
print(len(train), len(test))

ハッシュ値(sha256)は、元データが差し替わっていないかを確かめるための指紋です。値が変わっていたら、結果が違っても不思議ではありません。

ルール6・7:加工をコードに残し、結果を突き合わせる

ルール6:加工はコードで、途中で確認する

欠損値の除外、外れ値の除去、列名の変更は、すべてセルに書きます。そのとき、処理の前後で行数を表示します。たとえば「欠損除外で1200行→1187行」のように出力が残っていれば、他の人が再実行して食い違ったときに、どの段階でずれたかを特定できます。除外の理由(例:「入力ミスと判断」)も1行添えます。

ルール7:結果を控えて再実行後に比べる

冒頭のMarkdownに、主要な結果を数値で書いておきます(例:平均、係数、精度)。全セル実行のあと、その数値と一致するかを見ます。一致しない場合は、次の表で原因を絞り込みます。

  • 件数が違う、まず疑うこと:データの差し替え、読み込み条件、見る場所:ハッシュ値、assert
  • 数値が毎回少し変わる、まず疑うこと:シード未指定、乱数の消費順、見る場所:設定セル、random_state の渡し方
  • 関数がない・警告が出る、まず疑うこと:ライブラリの版が違う、見る場所:env.json
  • 再起動後だけエラー、まず疑うこと:状態への依存、実行順、見る場所:エラーが出たセルの上の定義
  • 自分のPCだけ動く、まず疑うこと:絶対パス、ローカル専用ファイル、見る場所:設定セルのパス

AIに任せる範囲と、人が確認する範囲

AIには、ノートブックの「実行順の依存」と「記録の抜け」を点検させると効果的です。任せるのは点検と下書きで、実際に再実行して数値が一致するかどうかは人が確認します。

渡す情報は、セルのコードとエラー文です。データそのものは貼らず、列名と型、行数程度にとどめます。氏名や顧客情報などの機密データは、ダミーの値に置き換えてください。

依頼文の例です。

以下はJupyter Notebookのセルを上から順に並べたコードです(データは含みません)。
再現性の観点で点検してください。
- 上から順に実行したときに、未定義の変数を使っているセルはないか
- 絶対パスや、手作業で編集したファイルへの依存はないか
- 乱数を使う箇所で、シードが指定されていないものはないか
- ライブラリの版を記録するセルは足りているか
問題点は「セル番号/理由/修正案」の表で出し、修正コードは修正案のみ示してください。

[ここにセルのコードを貼る]

AIの指摘は、そのまま信じず、再起動して全セル実行した結果で確かめます。「問題なし」という返答は、実行の成功を意味しません。

公開前チェックリスト

  • [ ] 冒頭に目的・データ名・取得日・実行方法・主要な結果の数値がある
  • [ ] カーネルを再起動し、全セルを上から実行してエラーがない
  • [ ] パスは相対パスで、設定セルの1か所にある
  • [ ] 元データは未編集で、ハッシュ値を控えた
  • [ ] 主要ライブラリの版を env.json などに書き出した
  • [ ] シードは1か所で決め、分割は整数、推定器は RandomState 等で渡している
  • [ ] 加工の前後で件数を確認している
  • [ ] 再実行後の数値が控えと一致した

ここまでそろえば、数か月後の自分や、初めて開く同僚が、同じ手順で同じ数値にたどり着ける可能性は大きく上がります。完全な再現には、OSや外部サービスの違いまで関わることがあるため、チームで共有する場合は、環境そのものを定義するファイルの整備も検討してください。

出典・参考資料