カオスなPython環境を5分で診断・整理してくれたClaude Codeとuv移行のすすめ

この記事はTVer Advent Calendar 2025 6日目の記事です。

こんにちは。TVerで広告周りのデータサイエンティストをしている土田です。

TVerでは全エンジニアがClaude Codeを利用できるようになっており、私も日々の業務で活用しています。 先日、「負の二項分布でストリーミング広告のリーチを予測してみた - 書籍の理論が通用しなかった原因とその解決」という記事を執筆する際に、ローカルでのデータ分析環境をゼロから構築し直す機会がありました。その過程で、Claude Codeのディレクションに従いながら、uvというモダンなPythonパッケージマネージャーを活用したところ、非常にスムーズに環境構築ができたので、その経緯と手順をご紹介します。

背景:なぜ環境を整理したのか

執筆のモチベーション

前述の記事「負の二項分布でストリーミング広告のリーチを予測してみた」を執筆するにあたって、Claude CodeとVSCode上で対話しながら分析を進めたいという強い思いがありました。

データ分析の現場では、以下のような場面が頻繁にあります。

  • コードを書いている途中で「この実装で合っているか?」を確認したい
  • エラーが出たときに素早く原因を特定して修正したい
  • グラフの可視化方法について最適な手法を提案してほしい
  • 複雑な統計モデルの実装について相談したい

従来はブラウザでClaude.aiを開いて質問し、コードをコピーし、結果を連携してまた質問と煩雑なフローをとっていました。しかし、Claude CodeをVSCodeに統合すれば、コードエディタから離れることなくAIと対話しながら分析を進められるようになります。

VSCodeでClaude CodeとJupyter Notebookを使って負の二項分布のリーチカーブ分析を対話的に進めている画面

上の画像は、VSCodeでClaude CodeとJupyter Notebookを使って対話しながら分析している様子(デモ)です。 Claude Codeがコードを提案し、その場でJupyter Notebookに挿入して実行、結果を確認までを行うことができます。

この「シームレスなAI支援」は、データ分析の生産性を劇的に向上させます。特に、Jupyter Notebookで試行錯誤しながら分析を進める場合、Claude Codeが隣にいる感覚でコーディングできるのは大きなメリットです。

ローカル環境の課題

当時の私のローカルPython環境は数年の利用や開発方針の変化、個人的な嗜好のトレンド(と自身の理解不足)でとてもカオスな状態になっていました。。。

  • 複数のパッケージ管理ツールが混在: pyenv, pipenv, pip, Anacondaが共存
  • Python本体も複数インストール: システムPython、Homebrew版、Python.org版、pyenv管理版
  • ディスク容量の圧迫: pyenv管理下のPythonだけで5.1GB
  • 環境の不透明性: どのツールで何を管理しているか不明瞭

このような状態では、Claude CodeとJupyter環境を安定して動かすことが難しいと判断しました。

また、せっかく環境を整理するなら、最新のベストプラクティスに則った構成にしたいと考えました。そこで注目したのがuvというモダンなPythonパッケージマネージャーです。

uvを選んだ理由

uvは2024年にリリースされた新しいパッケージマネージャーで、以下の特徴があります。

  • 高速: Rustで実装され、pipの10-100倍の速度
  • シンプル: プロジェクトごとに仮想環境を自動管理
  • 再現性: pyproject.tomluv.lockで厳密な依存関係管理
  • 統合的: Python本体のバージョン管理も可能

これなら、Claude Codeとの相性も良く、クリーンな分析環境を構築できると考えました。 また、現在広告チームで開発しているシステムもuvを採用しているため、個人環境と業務環境の整合性も取れます。

環境整理の実践

Claude Codeに依頼して、ローカル環境の整理とuv環境の構築を行いました。

Phase 1: 現状調査

まず、Claude Codeに現在のPython環境の調査を依頼しました。 依頼した内容は以下の通りです。

調査項目:

  • インストールされているPythonのバージョンと場所
  • パッケージ管理ツールの状況(pip, pipenv, pyenv, poetry等)
  • 関連ディレクトリの確認(~/.pyenv, ~/Library/Python等)
  • 環境変数(PATH等)の確認
  • システムPython依存の調査

プロンプトは以下のようにしました (ちなみに、このプロンプトもclaudeと対話して作成しました)

# macOS Python環境の整理とuv + Jupyter環境の構築

## 背景
現在のローカルPython環境が複数のパッケージ管理ツールが混在しており整理が必要です。
uvを使った仮想環境でJupyter NotebookをVSCodeから使用したいです。

## 環境情報
- OS: macOS
- 希望するパッケージ管理: uv(インストール済み)
- Anaconda/Miniconda: 未使用
- 壊したくない既存プロジェクト: 特になし(全体的に整理してOK)

## 依頼内容

### Phase 1: 現状調査
以下を調査して、現状のレポートを作成してください:

1. **Pythonの状況**
   - インストールされているPythonのバージョンと場所
   - システムPythonの確認

2. **パッケージ管理ツールの状況**
   - pip, pipx, pyenv, poetry, conda等の有無
   - Homebrew経由でインストールされたPython関連パッケージ

3. **関連ディレクトリの確認**
   - ~/.local/bin, ~/.pyenv, ~/.poetry, ~/Library/Python 等
   - 既存の仮想環境(.venv, venv等)があるプロジェクト

4. **環境変数**
   - PATH内のPython関連パス
   - PYTHONPATH, VIRTUAL_ENV等

5. **システムPython依存の調査**
   - macOSや他のツールがシステムPythonに依存しているか確認

### Phase 2: 整理方針の提案
調査結果をもとに以下を提案してください:
- 削除しても安全なもの
- 残すべきもの(理由とともに)
- 削除による影響範囲
- 推奨する整理手順

**この段階で一度確認を取ってから次に進んでください**

### Phase 3: 環境整理の実行
承認を得てから、提案した整理を実行してください。

### Phase 4: uv環境の構築
1. uvのセットアップ確認・更新
2. グローバルに使うツール(あれば)のuv tool install
3. Jupyter用のサンプルプロジェクト作成
   - uv init でプロジェクト作成
   - jupyter notebook(またはjupyterlab)のインストール
   - VSCodeで使用するための設定方法の説明

### Phase 5: ベストプラクティスの説明
今後のワークフローについて説明してください:
- 新規プロジェクト作成時の手順
- パッケージの追加・削除方法
- VSCodeでの仮想環境の選択方法
- .python-version や pyproject.toml の管理方針

## 注意事項
- 破壊的な操作(削除、アンインストール等)の前には必ず確認を取ってください
- 不明点があれば都度質問してください
- バックアップが必要なものがあれば事前に教えてください

Claude Codeは複数のコマンドを次々と実行し、約5分で詳細なレポートを作成してくれました。

調査結果(抜粋):

場所 バージョン サイズ 備考
/usr/bin/python3 3.9.6 - macOSシステムPython
/opt/homebrew/bin/python3 3.13.2 - Homebrew
~/.pyenv/versions/3.9.6 3.9.6 1.6GB pyenv管理
~/.pyenv/versions/anaconda3 Anaconda 3.2GB pyenv経由
/Library/Frameworks/Python.framework/ 3.11, 3.12 611MB Python.org版

合計で約5.7GBのディスク容量を使用していることが判明しました。

Phase 2: 整理方針の提案

Claude Codeは調査結果をもとに、削除しても安全なもの、残すべきものを明確に提案してくれました。

削除対象:

  • pyenvとその管理下のPython(5.1GB)
    • 理由: uvでPythonバージョン管理が可能なため不要。大容量のディスク使用
  • Python.org公式インストーラ版(611MB)
    • 理由: Homebrew版とuvで管理するため、手動インストール版は不要
  • pipenv(Homebrewパッケージ)
    • 理由: uvを使用するため、従来のパッケージマネージャーは不要
  • ユーザー領域のPythonパッケージ(~/Library/Python/3.9/
    • 理由: システムPythonへのグローバルインストールは環境を汚染。uv管理の仮想環境で代替

保持するもの:

  • macOSシステムPython(削除不可)
  • Homebrew Python(他のパッケージが依存)
  • uv(メインのパッケージマネージャーとして使用)

重要なのは、Claude Codeが削除による影響範囲も明示してくれた点です。例えば、Homebrewのいくつかのパッケージがpipenvに依存しているため、アンインストール時に警告が出る可能性があることを事前に教えてくれました。

Phase 3: 環境整理の実行

承認後、Claude Codeが以下の作業を自動実行しました。

# 1. シェル設定のバックアップ
cp ~/.bash_profile ~/.bash_profile.backup

# 2. pyenv削除
rm -rf ~/.pyenv

# 3. ユーザー領域のPythonパッケージ削除
rm -rf ~/Library/Python/3.9

# 4. pipenv削除
brew uninstall pipenv

# 5. pyenv削除(Homebrew)
brew uninstall pyenv

# 6. シェル設定のクリーンアップ
# .bash_profileからpyenv/pipenv関連の設定を削除

# 7. uvを最新版に更新
uv self update

Python.org版の削除は管理者権限が必要だったため、Claude Codeがコマンドを提示し、私の方で手動で実行しました。

sudo rm -rf /Library/Frameworks/Python.framework/Versions/3.11
sudo rm -rf /Library/Frameworks/Python.framework/Versions/3.12
sudo rm -rf /Library/Frameworks/Python.framework/Versions/Current
sudo rm /usr/local/bin/python3*

結果: 約5.7GBのディスク容量を解放し、Python環境がシンプルになりました。

Phase 4: uv + Jupyter環境の構築

次に、Claude Codeにテスト環境用のJupyter環境構築を依頼しました。

# プロジェクト初期化
cd /path/to/test-project
uv init --name test-project --python 3.13

# 必要なパッケージをインストール
uv add jupyter pandas numpy matplotlib scikit-learn

パッケージのダウンロードとインストールは約15秒で完了しました(従来のpipだと数分かかることも)。

生成されたファイル:

test-project/
├── .venv/              # uv管理の仮想環境
├── .python-version     # Python 3.13指定
├── pyproject.toml      # プロジェクト設定
├── uv.lock            # 依存関係ロックファイル
└── notebooks/
    └── test.ipynb     # テスト用ノートブック

pyproject.toml(自動生成):

[project]
name = "test-project"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
    "jupyter>=1.1.1",
    "matplotlib>=3.10.7",
    "numpy>=2.3.5",
    "pandas>=2.3.3",
    "scikit-learn>=1.7.2",
]

Phase 5: VSCodeでの動作確認

Claude Codeは、テスト用のJupyter Notebookも自動作成してくれました。

notebooks/test.ipynb(抜粋):

# パッケージのインポートテスト
import numpy as np
import pandas as pd
import matplotlib

print(f"NumPy version: {np.__version__}")
print(f"Pandas version: {pd.__version__}")
print(f"Matplotlib version: {matplotlib.__version__}")

VSCodeでノートブックを開き、Python Interpreter.venv/bin/pythonに設定すると、すべてのセルが問題なく実行できました。

Claude Codeによる環境構築の利点

今回、Claude Codeに環境構築を依頼したことで、以下のメリットがありました。

1. 包括的な調査

人間が手作業で調べると見落としがちな箇所(環境変数、Homebrew依存関係など)も、Claude Codeは網羅的にチェックしてくれました。

2. リスク評価

削除する前に影響範囲を明示してくれたため、安心して作業を進められました。

3. コマンドの自動実行

複数の調査コマンドを自動で実行してくれるので、調査時間を大幅に短縮できました。

4. ベストプラクティスの適用

uvという最新のツールを提案し、適切なプロジェクト構成(pyproject.toml, uv.lock)を自動生成してくれました。

5. ドキュメント化

実行したコマンドと結果がすべて記録されるため、後から手順を振り返ることができます。

uv + Jupyter環境のワークフロー

構築した環境での日常的なワークフローは以下の通りです。

プロジェクト開始時

cd /path/to/project

# 依存関係を同期(uv.lockから復元)
uv sync

# Jupyter起動
uv run jupyter notebook

パッケージ追加時

# パッケージを追加
uv add seaborn

# すぐに使える(自動で.venvにインストール済み)
uv run jupyter notebook

VSCodeでの使用

  1. VSCodeでプロジェクトフォルダを開く
  2. Cmd+Shift+P → "Python: Select Interpreter"
  3. .venv/bin/pythonを選択
  4. Jupyter Notebookを開くと自動的にカーネルが検出される

既存プロジェクトのクローン時

git clone <repository>
cd <project>

# 依存関係を自動インストール
uv sync

# すぐに実行可能
uv run jupyter notebook

Claude Codeとの分析ワークフロー

環境構築後、実際にClaude CodeとVSCode上で対話しながら分析を進めました。

Claude Codeとの分析対話の実例

環境構築後、実際にClaude CodeとVSCode上で対話しながら、リーチカーブ分析を進めました。以下、実際の対話の抜粋です。 (pythonコードについては一部簡略化していますが、対話の流れを感じていただければと思います)

対話例1: フリークエンシー分布の可視化

私: フリークエンシー分布のデータがついて、予測と実測値に誤差がありそうです。確認してみてください。

Claude Code:

ご指摘ありがとうございます!確認させてください。

# データ読み込み
df_frequency = pl.read_csv("data/frequency.csv")

# 可視化
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(df_frequency["f"], df_frequency["prop"],
       alpha=0.7, label='実測値')

# 負の二項分布の予測値をプロット
f_range = np.arange(0, 21)
freq_pred = nbinom.pmf(f_range, n=alpha, p=alpha/(g+alpha))
ax.plot(f_range, freq_pred, 'o-', label='負の二項分布')

ax.set_xlabel('接触回数')
ax.set_ylabel('割合')
ax.legend()
plt.show()

確かに、f=0〜2の低頻度域で予測と実測にずれがありますね。特にf=0(非接触者)で4%程度の誤差があります。


対話例2: ユーザー異質性の仮説検証

私: ユーザーが二極化(ライト層とヘビー層)しているという仮説はどうでしょうか?混合負の二項分布でモデル化できますか?

Claude Code:

素晴らしい仮説です!混合負の二項分布モデルを実装してみましょう。

from scipy.optimize import minimize

def predict_reach_mixed(g, alpha1, alpha2, weight):
    """2つの負の二項分布を混合"""
    r1 = 1 - (alpha1 / (g + alpha1)) ** alpha1
    r2 = 1 - (alpha2 / (g + alpha2)) ** alpha2
    return weight * r1 + (1 - weight) * r2

# パラメータ推定(詳細は省略)
alpha1, alpha2, weight = estimate_mixed_model(df_reach)

print(f"ライト層: α={alpha1:.3f}, 割合={weight*100:.1f}%")
print(f"ヘビー層: α={alpha2:.3f}, 割合={(1-weight)*100:.1f}%")
print(f"MAPE: {mape:.2f}%")

(実行結果)

ライト層: α=0.143, 割合=65.2%
ヘビー層: α=2.881, 割合=34.8%
MAPE: 9.75%

単純モデル(12.79%)から3.04%の改善が見られました。ただし、対数変換モデル(8.39%)にはまだ及びません。それでも、ライト層65%・ヘビー層35%という推定結果は、ユーザーセグメントの理解に役立ちそうです。


対話例3: kパラメータの導入と最適化

私: kパラメータを導入したモデルを実装して、k=1から5まで試してみてください。

Claude Code:

kパラメータを考慮した負の二項分布モデルを実装します。これは「1日あたりのimpression数」を表現するパラメータです。

def predict_reach_nbinom_with_k(g, alpha, k):
    """kパラメータを考慮した負の二項分布によるリーチ予測"""
    return 1 - (k * alpha / (g + k * alpha)) ** alpha

# k=1〜5で検証
for k in range(1, 6):
    alpha_opt = optimize_alpha(df_reach, k)
    r_pred = predict_reach_nbinom_with_k(df_reach["g"], alpha_opt, k)
    mape = calculate_mape(df_reach["r"], r_pred)
    print(f"k={k}: α={alpha_opt:.4f}, MAPE={mape:.2f}%")

(実行結果)

k=1: α=0.2207, MAPE=12.77%
k=2: α=0.3885, MAPE=2.69%
k=3: α=0.7009, MAPE=5.03%
k=4: α=1.6324, MAPE=11.26%
k=5: α=10.0000, MAPE=16.74%

驚異的な発見です!k=2でMAPEが2.69%まで改善しました。通常モデル(k=1)の12.77%と比較すると、10.08%もの改善です。これは「広告接触が1日あたり平均2回のペースで発生している」という仮説を示唆しており、広告配信の時間的パターンを捉えた結果と考えられます。


これらの対話を通じて、仮説の提案 → コード実装 → 結果の解釈というサイクルを、VSCode上でClaude Codeと高速に回すことができました。

特に重要なのは、Claude Codeが、

  • 統計的な仮説を提案(混合モデル、初期値の影響など)
  • 実装可能なコードをその場で生成(最適化、可視化含む)
  • 結果を統計的に解釈(MAPE改善、理論的背景の説明)

してくれる点です。Jupyter Notebook上でこのような対話ができることで、データ分析の試行錯誤が劇的に効率化されました。

まとめ

Claude Codeとuvを活用することで、以下を実現できました。

  1. ローカル環境のクリーンアップ: 5.7GBのディスク容量を解放
  2. モダンな開発環境の構築: uvによる高速で再現性の高い環境
  3. Jupyter + Claude Codeの統合: VSCode上でAIと対話しながら分析
  4. 効率的なワークフロー: パッケージ管理、環境切り替えが簡単

特に、Claude CodeとVSCode上で対話しながら分析を進められる環境が整ったことで、データ分析の生産性が大幅に向上しました。今後の業務においても、この環境をフル活用していきたいと思います。

参考リンク


TVerでは、データドリブンな意思決定を支援するデータサイエンティストを募集しています。興味のある方は、TVer採用サイトをご確認ください。