404 Not Found

404 Not Found


nginx

【Pandas総合プロジェクト】複数ソース統合・品質監査・merge連鎖・pivot分析・Stylerレポート

実際のプロジェクトでは、1つのテーブルだけで完結することは決してありません。5つのCSVファイル+1つのExcelファイル+データベースクエリを4回mergeし、3つのディメンションでgroupbyし、2つのクロス集計にpivotし、1つの洗練されたレポートに仕上げる——これが現実です。このレッスンはコース全体のグランドフィナーレとして、前24レッスンで学んだすべてのスキルを1つのプロジェクトに統合します:複数ソース統合 → 品質監査 → 複雑な結合 → 多次元分析 → 自動化レポート。

警告: 以下のコードはローカルのPython環境で実行してください。

1. このレッスンで学ぶこと



2. プロジェクト背景:越境EC分析

(1) タスク

ボブは越境EC事業の第1四半期〜第3四半期のデータを分析する必要があります:4つのCSV(orders/products/customers/regions)+1つのSQLiteデータベース(inventory)→ 統合 → 分析 → レポート作成。

(2) 全体ワークフロー

100%
graph TB
    A["5つのデータソースを読み込み"] --> B["データ品質監査"]
    B --> C["4テーブルmerge"]
    C --> D["クリーニングパイプライン"]
    D --> E["多次元groupby"]
    E --> F["pivotクロス分析"]
    F --> G["Stylerレポート"]
    G --> H["マルチシート出力"]
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。


3. 複数ソースのデータ読み込み

▶ サンプル:5つのデータソースの読み込み(難易度:★★★☆☆)

TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。
PYTHON
import pandas as pd
import numpy as np
import sqlite3
from io import StringIO, BytesIO

# ============================================
# ステップ1:複数ソースのデータ読み込み
# ============================================

np.random.seed(42)

# ソース1:顧客データ(CSV)
customers = pd.DataFrame({
    'customer_id': range(1, 501),
    'name': [f'Customer_{i:04d}' for i in range(1, 501)],
    'segment': np.random.choice(['Consumer', 'Corporate', 'Home Office'], 500),
    'city': np.random.choice(['New York', 'Los Angeles', 'Chicago', 'Houston', 'London', 'Tokyo'], 500),
    'country': np.random.choice(['US', 'US', 'US', 'US', 'UK', 'JP'], 500)
})

# ソース2:商品データ(CSV)
products = pd.DataFrame({
    'product_id': range(1, 51),
    'product_name': [f'Product_{i:02d}' for i in range(1, 51)],
    'category': np.random.choice(['Electronics', 'Clothing', 'Home', 'Sports', 'Books'], 50),
    'unit_price': np.round(np.random.uniform(10, 500, 50), 2)
})

# ソース3:注文データ(CSV)
orders = pd.DataFrame({
    'order_id': [f'ORD-{i:05d}' for i in range(1, 2001)],
    'customer_id': np.random.randint(1, 501, 2000),
    'product_id': np.random.randint(1, 51, 2000),
    'order_date': pd.to_datetime(np.random.choice(
        pd.date_range('2024-01-01', '2024-09-30'), 2000)),
    'quantity': np.random.randint(1, 10, 2000),
    'discount': np.random.choice([0, 0.05, 0.1, 0.2, 0.3], 2000)
})

# ソース4:地域データ(Excel)
regions = pd.DataFrame({
    'country': ['US', 'UK', 'JP', 'DE', 'FR'],
    'region': ['North America', 'Europe', 'Asia Pacific', 'Europe', 'Europe'],
    'currency': ['USD', 'GBP', 'JPY', 'EUR', 'EUR']
})

# ソース5:在庫データ(SQLite)
conn = sqlite3.connect(':memory:')
inventory = pd.DataFrame({
    'product_id': range(1, 51),
    'stock': np.random.randint(0, 500, 50),
    'reorder_level': np.random.randint(20, 100, 50)
})
inventory.to_sql('inventory', conn, index=False, if_exists='replace')

# データベースから読み込み
inv_df = pd.read_sql('SELECT * FROM inventory', conn)
conn.close()

print(f"✅ 読み込み完了: customers({len(customers)}), products({len(products)}), "
      f"orders({len(orders)}), regions({len(regions)}), inventory({len(inv_df)})")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。


4. データ品質監査

▶ サンプル:品質監査(難易度:★★☆☆☆)

TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。
PYTHON
# ============================================
# ステップ2:データ品質監査
# ============================================

def audit_quality(df, name):
    """データフレームに対して品質監査を実行する"""
    issues = []
    # 欠損値
    missing = df.isnull().sum()
    if missing.sum() > 0:
        issues.append(f"欠損: {dict(missing[missing > 0])}")
    # 重複
    dups = df.duplicated().sum()
    if dups > 0:
        issues.append(f"重複: {dups}")
    # 型
    object_cols = df.select_dtypes(include='object').columns.tolist()
    if object_cols:
        issues.append(f"object型のカラム: {object_cols}")
    status = "⚠️ 問題あり" if issues else "✅ クリーン"
    print(f"{name}: {status}")
    for issue in issues:
        print(f"  - {issue}")
    return issues

audit_quality(customers, 'Customers')
audit_quality(products, 'Products')
audit_quality(orders, 'Orders')
audit_quality(regions, 'Regions')
audit_quality(inv_df, 'Inventory')

# デモ用に問題を注入
orders.loc[np.random.choice(2000, 100, replace=False), 'discount'] = np.nan
dups = orders.sample(30)
orders = pd.concat([orders, dups], ignore_index=True)
print(f"\n問題注入後: ordersのshape = {orders.shape}")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。


5. 4テーブルmerge+クリーニング

▶ サンプル:複雑なmerge+pipeクリーニング(難易度:★★★☆☆)

TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。
PYTHON
# ============================================
# ステップ3-4:4テーブルmerge+クリーニング
# ============================================

def clean_orders(df):
    df = df.drop_duplicates(subset='order_id', keep='last')
    df['discount'] = df['discount'].fillna(0)
    return df

# ステップ1:注文データをクリーニング
clean_orders_df = orders.pipe(clean_orders)

# ステップ2:orders + productsをmerge
op = pd.merge(clean_orders_df, products, on='product_id', how='left')

# ステップ3:+ customersをmerge
opc = pd.merge(op, customers, on='customer_id', how='left')

# ステップ4:+ regionsをmerge
full = pd.merge(opc, regions, on='country', how='left')

# ステップ5:+ inventoryをmerge
full = pd.merge(full, inv_df, on='product_id', how='left')

# 派生カラム
full['revenue'] = full['unit_price'] * full['quantity'] * (1 - full['discount'])
full['cost_estimate'] = full['unit_price'] * full['quantity'] * 0.6
full['profit'] = full['revenue'] - full['cost_estimate']
full['month'] = full['order_date'].dt.to_period('M')
full['is_low_stock'] = full['stock'] < full['reorder_level']

print(f"✅ 統合データセット: {full.shape}")
print(f"カラム: {full.columns.tolist()}")
print(f"欠損値: {full.isnull().sum().sum()}")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。


6. 多次元groupby+pivot分析

▶ サンプル:多次元集計とクロス分析(難易度:★★★☆☆)

TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。
PYTHON
# ============================================
# ステップ5-6:多次元分析
# ============================================

# 1. 地域×カテゴリ別の売上
region_cat = full.groupby(['region', 'category']).agg(
    revenue=('revenue', 'sum'),
    orders=('order_id', 'count'),
    avg_order_value=('revenue', 'mean'),
    profit_margin=('profit', lambda x: x.sum() / full.loc[x.index, 'revenue'].sum())
).round(2)
print("=== 地域×カテゴリ別売上 ===")
print(region_cat.head(8))

# 2. 地域別月次トレンド
monthly_region = full.groupby(['month', 'region'])['revenue'].sum().unstack()
print(f"\n=== 地域別月次売上 ===\n{monthly_region.tail(3)}")

# 3. ピボットテーブル:セグメント×カテゴリ
seg_cat = pd.pivot_table(
    full, values='revenue', index='segment', columns='category',
    aggfunc='sum', margins=True, margins_name='合計'
).round(0)
print(f"\n=== セグメント×カテゴリ ピボット ===\n{seg_cat}")

# 4. 人気商品トップ
top_products = full.groupby('product_name').agg(
    revenue=('revenue', 'sum'),
    quantity=('quantity', 'sum'),
    avg_discount=('discount', 'mean')
).nlargest(5, 'revenue')
print(f"\n=== 人気商品トップ5 ===\n{top_products}")

# 5. 在庫不足アラート
low_stock = full[full['is_low_stock']].groupby('product_name').agg(
    stock=('stock', 'first'),
    reorder_level=('reorder_level', 'first'),
    total_orders=('order_id', 'count')
).sort_values('total_orders', ascending=False)
print(f"\n=== 在庫不足アラート ===\n{low_stock.head(5)}")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。


7. Stylerレポートとマルチシート出力

▶ サンプル:Stylerレポート+Excel出力(難易度:★★★☆☆)

TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。
PYTHON
# ============================================
# ステップ7:スタイル付きレポート+出力
# ============================================

# セグメント×カテゴリのピボットをスタイリング
styled_pivot = (seg_cat.style
    .format('${:,.0f}')
    .background_gradient(cmap='RdYlGn', axis=None)
    .set_caption('セグメント×カテゴリ別売上')
)

# 人気商品をスタイリング
styled_products = (top_products.style
    .format({'revenue': '${:,.0f}', 'quantity': '{:,}', 'avg_discount': '{:.1%}'})
    .bar(subset=['revenue'], color='lightblue')
    .highlight_max(subset=['revenue'], color='lightgreen')
)

# 在庫不足アラートをスタイリング
styled_stock = (low_stock.head(10).style
    .format({'stock': '{:.0f}', 'reorder_level': '{:.0f}', 'total_orders': '{:,}'})
    .background_gradient(subset=['total_orders'], cmap='YlOrRd')
    .set_caption('在庫不足アラート — 高需要商品')
)

# 複数シートでExcelに出力
output_path = 'ecommerce_report.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
    # サマリーシート
    summary = pd.DataFrame({
        'Metric': ['総売上', '総利益', '総注文数',
                    'ユニーク顧客数', 'ユニーク商品数', '平均注文金額',
                    '利益率'],
        'Value': [full['revenue'].sum(), full['profit'].sum(), len(full),
                  full['customer_id'].nunique(), full['product_id'].nunique(),
                  full['revenue'].mean(), full['profit'].sum() / full['revenue'].sum()]
    })
    summary.to_excel(writer, sheet_name='Summary', index=False)

    # 地域×カテゴリ
    region_cat.to_excel(writer, sheet_name='Region-Category')

    # 月次トレンド
    monthly_region.to_excel(writer, sheet_name='Monthly-Trend')

    # セグメント×カテゴリ(スタイル付き)
    styled_pivot.to_excel(writer, sheet_name='Segment-Category')

    # 人気商品
    top_products.to_excel(writer, sheet_name='Top-Products')

print(f"✅ レポート出力完了: {output_path}")

# 最終サマリー
print("\n" + "=" * 50)
print("  越境EC総合分析 完了")
print("=" * 50)
print(f"  売上: ${full['revenue'].sum():,.0f}")
print(f"  利益: ${full['profit'].sum():,.0f}")
print(f"  利益率: {full['profit'].sum() / full['revenue'].sum():.1%}")
print(f"  トップ地域: {full.groupby('region')['revenue'].sum().idxmax()}")
print(f"  トップカテゴリ: {full.groupby('category')['revenue'].sum().idxmax()}")
print(f"  在庫不足商品数: {len(low_stock)}")
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)して実行してください。実際の値はpandasのバージョンにより若干異なる場合があります。

❓ よくある質問

Q 複数データソースの形式を統一するにはどうすればよいですか?
A 3つのステップで標準化します:(1)カラム名の統一——同じキーには同じ名前を使用します(例:すべてでcustomer_id)。(2)型の統一——すべての日付カラムをto_datetimeで変換し、すべてのIDカラムをint型にします。(3)エンコーディングの統一——UTF-8を優先し、GBKはUTF-8に変換します。merge前にキーカラムのdtypeとユニーク値を確認し、マッチ可能であることを確認してください。
Q データ品質をどのように定量化しますか?
A 4つのディメンションで評価します:(1)完全性(欠損率=欠損数÷総数、目標は5%未満)。(2)一貫性(キーカラムが関連テーブルにマッチ先を持つか?)。(3)正確性(外れ値の割合、例:負の金額や極端な値)。(4)適時性(データの最終更新はいつか——古すぎないか?)。各ディメンションを1〜5でスコアリングし、総合評価を行います。
Q merge連鎖が長くなりすぎた場合はどうすればよいですか?
A ステップごとにmergeし、各結合の後に検証します——毎回行数と欠損値を確認してください。5テーブルのmergeを一度に書かず、4ステップに分割します:orders+products → +customers → +regions → +inventory。各ステップの後にprint(shape, missing)で正確性を確認してから次に進みます。
Q レポート作成を自動化するにはどうすればよいですか?
A ExcelWriterで複数シート(サマリー+ディメンション別分析+スタイル付きピボット)を生成するか、Styler.to_html()でWebベースのレポートを出力します。さらに発展させると:Jupyter Notebook+nbconvertでPDFを自動生成できます。究極のアプローチは:papermillでノートブックをパラメータ化し、スケジュール実行でレポートを自動生成することです。
Q BIツールと比べてどうですか?
A Pandasは柔軟なカスタム分析に優れています——BIツールの組み込み機能に制限されず、任意に複雑なロジックを実装できます。BIツール(Tableau/Power BI)は標準化されたダッシュボードやインタラクティブな探索に適しています——ドラッグ&ドロップでのチャート作成は高速ですが、複雑な計算には制約があります。戦略:深い分析とデータ準備にはPandasを使い、視覚的なプレゼンテーションにはBIツールを使います。
Q 多次元ピボットテーブルをどのように構築しますか?
A indexに複数のカラムを渡します:pd.pivot_table(df, index=['region','segment'], columns='category')。これによりMultiIndexのカラムが生成されます。margins=Trueを設定すると行合計と列合計が追加されます。クロス分析とは、1つのディメンションを行に、1つを列に、1つを値にすることです——これが3次元データを表示する最も直感的な方法です。
Q 在庫不足アラートをどのように実装しますか?
A stockとreorder_levelを比較します——df[df['stock'] < df['reorder_level']]。優先順位を付けるには、注文数でソートします:在庫不足+注文数が多い=最も緊急。Stylerのbackground_gradientで緊急度を示し、赤は「即座に補充が必要」を意味します。

📖 まとめ


📝 練習問題

  1. 基礎(難易度:★☆☆☆☆):2つのデータフレーム(customers+orders)を作成し、mergeして地域別総売上を計算し、indicatorパラメータでマッチ率を確認してください。
  2. 中級(難易度:★★☆☆☆):3つのデータソース(customers/products/orders)をシミュレートし、3回のmerge → クリーニング → 多次元groupby集計 → pivot_tableクロス集計 → Stylerフォーマットを実行してください。
  3. チャレンジ(難易度:★★★☆☆):このレッスンのプロジェクトを完成させてください:5ソースの読み込み → 品質監査 → 4テーブルmerge → pipeクリーニング → 多次元groupby+pivot → Stylerレポート → ExcelWriterマルチシート出力。

<- 前のレッスン:プロジェクト - 時系列分析 | コース修了 ->

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%