STEP 12:データ検証とバリデーション

✅ STEP 12: データ検証とバリデーション

データ品質をチェックして信頼性を確保しよう

📋 このステップで学ぶこと

  • データ品質チェックの重要性と6つの品質側面
  • スキーマ検証(データ型、カラム存在チェック)
  • 範囲チェック、NULLチェック、重複チェック
  • 再利用可能な検証関数の作成
  • Great Expectations入門
  • 実践演習:データ品質レポート作成

⏱️ 学習時間の目安:2時間

📝 練習問題:10問(基礎4問・応用4問・発展2問)

🎯 1. データ品質チェックの重要性

1-1. なぜデータ検証が必要なのか?

データ検証(Validation)とは、データが正しいかどうかをチェックすることです。
ETLパイプラインでは、「Garbage In, Garbage Out(ゴミを入れればゴミが出る)」という言葉があるように、不正なデータが入ると、出力も信頼できなくなります

📚 例え話:食材の検品

レストランで料理を作る前に、食材の品質をチェックしますよね。

・野菜は新鮮か?(適時性)
賞味期限は切れていないか?(妥当性)
傷んでいないか?(正確性)
・注文した食材が全部揃っているか?(完全性)

データも同じように、使う前に品質チェックが必要です!

⚠️ データ品質が悪いと…
  • 間違った分析結果:売上が実際より高く/低く見えてしまう
  • ビジネス判断ミス:誤ったデータに基づいて意思決定
  • システムエラー:予期しないNULLや型不一致で処理が止まる
  • 顧客への影響:誤った請求や配送先ミスなど

1-2. データ品質の6つの側面

データ品質の6つの側面
品質項目 説明 チェック例
完全性 必要なデータがすべて揃っているか 必須カラムにNULLがないか、レコード数が期待通りか
正確性 データが正しい値か 計算結果が正しいか、入力ミスがないか
一貫性 データ形式が統一されているか 日付形式が統一されているか、コード体系が一致するか
適時性 データが最新か 更新日時が期待範囲内か、古すぎるデータがないか
妥当性 データが妥当な範囲内か 年齢が0〜120の範囲か、価格が正の値か
一意性 重複データがないか 主キーが一意か、同じレコードが複数ないか

📋 2. スキーマ検証

2-1. スキーマとは?

スキーマ(Schema)とは、データの構造定義です。
「どんなカラムがあって、どんなデータ型か」を定義します。

📝 スキーマで定義する項目
  • カラム名:どんなカラムが必要か
  • データ型:int64、float64、object(文字列)など
  • NULL許容:欠損値を許可するか
  • 制約:一意性、外部キーなど

2-2. 基本的なスキーマチェック

# ===== データ型のチェック ===== import pandas as pd df = pd.DataFrame({ ‘user_id’: [1, 2, 3], ‘name’: [‘山田’, ‘佐藤’, ‘鈴木’], ‘age’: [25, 30, 28], ‘email’: [‘yamada@ex.com’, ‘sato@ex.com’, ‘suzuki@ex.com’] }) # 期待されるスキーマ expected_schema = { ‘user_id’: ‘int64’, ‘name’: ‘object’, ‘age’: ‘int64’, ‘email’: ‘object’ } print(“=== 現在のスキーマ ===”) print(df.dtypes) print(“\n=== スキーマ検証 ===”) for col, expected_dtype in expected_schema.items(): if col not in df.columns: print(f”❌ カラム ‘{col}’ が存在しません”) elif str(df[col].dtype) != expected_dtype: print(f”❌ カラム ‘{col}’ の型が違います: {df[col].dtype} (期待: {expected_dtype})”) else: print(f”✅ カラム ‘{col}’ OK ({expected_dtype})”)
【実行結果】 === 現在のスキーマ === user_id int64 name object age int64 email object dtype: object === スキーマ検証 === ✅ カラム ‘user_id’ OK (int64) ✅ カラム ‘name’ OK (object) ✅ カラム ‘age’ OK (int64) ✅ カラム ‘email’ OK (object)

2-3. 必須カラムの存在チェック

# ===== 必須カラムの確認 ===== import pandas as pd df = pd.DataFrame({ ‘user_id’: [1, 2, 3], ‘name’: [‘山田’, ‘佐藤’, ‘鈴木’] # emailとageがない! }) # 必須カラムのリスト required_columns = [‘user_id’, ‘name’, ‘email’, ‘age’] print(“=== 必須カラムチェック ===”) missing_columns = [] for col in required_columns: if col in df.columns: print(f”✅ ‘{col}’ 存在”) else: print(f”❌ ‘{col}’ 不足”) missing_columns.append(col) if missing_columns: print(f”\n⚠️ 不足カラム: {missing_columns}”) else: print(“\n✅ すべての必須カラムが存在します”)
【実行結果】 === 必須カラムチェック === ✅ ‘user_id’ 存在 ✅ ‘name’ 存在 ❌ ‘email’ 不足 ❌ ‘age’ 不足 ⚠️ 不足カラム: [‘email’, ‘age’]

2-4. 再利用可能なスキーマ検証関数

# ===== 再利用可能な検証関数 ===== import pandas as pd def validate_schema(df, schema): “”” DataFrameのスキーマを検証 Args: df: 検証するDataFrame schema: 期待されるスキーマ(辞書: {カラム名: データ型}) Returns: tuple: (成功フラグ, エラーリスト) “”” errors = [] # カラムの存在チェック for col in schema.keys(): if col not in df.columns: errors.append(f”カラム ‘{col}’ が存在しません”) # データ型チェック for col, expected_dtype in schema.items(): if col in df.columns: actual_dtype = str(df[col].dtype) if actual_dtype != expected_dtype: errors.append( f”カラム ‘{col}’ の型が違います: ” f”{actual_dtype} (期待: {expected_dtype})” ) # 余分なカラムの警告(エラーではない) extra_cols = set(df.columns) – set(schema.keys()) if extra_cols: print(f”ℹ️ 追加カラム(スキーマ外): {extra_cols}”) # 結果 if errors: print(“❌ スキーマ検証失敗:”) for error in errors: print(f” – {error}”) return False, errors else: print(“✅ スキーマ検証成功”) return True, [] # ===== 使用例 ===== df = pd.DataFrame({ ‘user_id’: [1, 2, 3], ‘name’: [‘山田’, ‘佐藤’, ‘鈴木’], ‘age’: [25, 30, 28], ‘extra_col’: [‘x’, ‘y’, ‘z’] # スキーマ外のカラム }) schema = { ‘user_id’: ‘int64’, ‘name’: ‘object’, ‘age’: ‘int64’, ‘email’: ‘object’ # dfに存在しない } success, errors = validate_schema(df, schema)
【実行結果】 ℹ️ 追加カラム(スキーマ外): {‘extra_col’} ❌ スキーマ検証失敗: – カラム ‘email’ が存在しません

🔍 3. 範囲チェック・NULLチェック・重複チェック

3-1. 範囲チェック

# ===== 値が妥当な範囲内かチェック ===== import pandas as pd df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 4, 5], ‘age’: [25, 30, -5, 150, 28], # -5と150は異常 ‘price’: [1000, 1500, 0, 2000, -100] # 0と-100は異常 }) print(“=== 元データ ===”) print(df) # 年齢の範囲チェック(0〜120) print(“\n=== 年齢の範囲チェック(0〜120)===”) age_invalid = df[(df[‘age’] < 0) | (df['age'] > 120)] if len(age_invalid) > 0: print(f”❌ 範囲外のデータ: {len(age_invalid)}件”) print(age_invalid[[‘user_id’, ‘age’]]) else: print(“✅ すべて範囲内”) # 価格の範囲チェック(1以上) print(“\n=== 価格の範囲チェック(1以上)===”) price_invalid = df[df[‘price’] < 1] if len(price_invalid) > 0: print(f”❌ 範囲外のデータ: {len(price_invalid)}件”) print(price_invalid[[‘user_id’, ‘price’]]) else: print(“✅ すべて範囲内”)
【実行結果】 === 元データ === user_id age price 0 1 25 1000 1 2 30 1500 2 3 -5 0 3 4 150 2000 4 5 28 -100 === 年齢の範囲チェック(0〜120)=== ❌ 範囲外のデータ: 2件 user_id age 2 3 -5 3 4 150 === 価格の範囲チェック(1以上)=== ❌ 範囲外のデータ: 2件 user_id price 2 3 0 4 5 -100

3-2. NULLチェック(欠損値チェック)

# ===== 欠損値のチェック ===== import pandas as pd import numpy as np df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 4], ‘name’: [‘山田’, np.nan, ‘鈴木’, ‘田中’], # 1件欠損 ‘email’: [‘yamada@ex.com’, ‘sato@ex.com’, None, ‘tanaka@ex.com’], # 1件欠損 ‘age’: [25, 30, np.nan, np.nan] # 2件欠損 }) print(“=== 元データ ===”) print(df) # 必須カラムのNULLチェック print(“\n=== 必須カラムのNULLチェック ===”) required_columns = [‘user_id’, ‘name’, ‘email’] for col in required_columns: null_count = df[col].isnull().sum() total_count = len(df) null_pct = (null_count / total_count * 100) if null_count > 0: print(f”❌ ‘{col}’: {null_count}件の欠損 ({null_pct:.1f}%)”) else: print(f”✅ ‘{col}’: 欠損なし”) # 全体の欠損値サマリー print(“\n=== 全体の欠損値サマリー ===”) null_summary = df.isnull().sum() null_summary = null_summary[null_summary > 0] print(null_summary)
【実行結果】 === 元データ === user_id name email age 0 1 山田 yamada@ex.com 25.0 1 2 NaN sato@ex.com 30.0 2 3 鈴木 None NaN 3 4 田中 tanaka@ex.com NaN === 必須カラムのNULLチェック === ✅ ‘user_id’: 欠損なし ❌ ‘name’: 1件の欠損 (25.0%) ❌ ‘email’: 1件の欠損 (25.0%) === 全体の欠損値サマリー === name 1 email 1 age 2 dtype: int64

3-3. 重複チェック

# ===== 重複データのチェック ===== import pandas as pd df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 2, 4], # user_id=2が重複 ‘email’: [‘a@ex.com’, ‘b@ex.com’, ‘c@ex.com’, ‘b@ex.com’, ‘d@ex.com’], ‘name’: [‘山田’, ‘佐藤’, ‘鈴木’, ‘佐藤’, ‘田中’] }) print(“=== 元データ ===”) print(df) # 特定カラムの重複チェック print(“\n=== user_idの重複チェック ===”) dup_user_id = df[df[‘user_id’].duplicated(keep=False)] if len(dup_user_id) > 0: print(f”❌ 重複あり: {len(dup_user_id)}件”) print(dup_user_id) else: print(“✅ 重複なし”) # 行全体の重複チェック print(“\n=== 行全体の重複チェック ===”) dup_rows = df[df.duplicated(keep=False)] if len(dup_rows) > 0: print(f”❌ 重複行: {len(dup_rows)}件”) print(dup_rows) else: print(“✅ 重複行なし”)
【実行結果】 === 元データ === user_id email name 0 1 a@ex.com 山田 1 2 b@ex.com 佐藤 2 3 c@ex.com 鈴木 3 2 b@ex.com 佐藤 4 4 d@ex.com 田中 === user_idの重複チェック === ❌ 重複あり: 2件 user_id email name 1 2 b@ex.com 佐藤 3 2 b@ex.com 佐藤 === 行全体の重複チェック === ❌ 重複行: 2件 user_id email name 1 2 b@ex.com 佐藤 3 2 b@ex.com 佐藤

3-4. 包括的なデータ品質レポート関数

# ===== 包括的な品質チェック関数 ===== import pandas as pd import numpy as np def data_quality_report(df): “”” DataFrameの品質レポートを生成 “”” print(“=” * 60) print(“データ品質レポート”) print(“=” * 60) # 基本情報 print(f”\n【1. 基本情報】”) print(f” 行数: {len(df):,}”) print(f” 列数: {len(df.columns)}”) print(f” メモリ使用量: {df.memory_usage(deep=True).sum() / 1024:.1f} KB”) # 欠損値 print(f”\n【2. 欠損値】”) null_counts = df.isnull().sum() null_pct = (null_counts / len(df) * 100).round(2) null_df = pd.DataFrame({ ‘欠損数’: null_counts, ‘欠損率(%)’: null_pct }) null_df = null_df[null_df[‘欠損数’] > 0] if len(null_df) > 0: print(null_df) else: print(” 欠損値なし ✅”) # 重複 print(f”\n【3. 重複】”) dup_count = df.duplicated().sum() if dup_count > 0: print(f” 重複行数: {dup_count} ❌”) else: print(f” 重複行なし ✅”) # データ型 print(f”\n【4. データ型】”) for col in df.columns: print(f” {col}: {df[col].dtype}”) # 数値カラムの統計 numeric_cols = df.select_dtypes(include=[np.number]).columns if len(numeric_cols) > 0: print(f”\n【5. 数値カラムの統計】”) stats = df[numeric_cols].describe().T[[‘min’, ‘max’, ‘mean’, ‘std’]] print(stats.round(2)) print(“\n” + “=” * 60) # ===== 使用例 ===== df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 2, 4], ‘age’: [25, np.nan, 30, 28, 35], ‘price’: [1000, 1500, 2000, 1500, 2500], ‘name’: [‘山田’, ‘佐藤’, ‘鈴木’, ‘佐藤’, ‘田中’] }) data_quality_report(df)
【実行結果】 ============================================================ データ品質レポート ============================================================ 【1. 基本情報】 行数: 5 列数: 4 メモリ使用量: 0.5 KB 【2. 欠損値】 欠損数 欠損率(%) age 1 20.0 【3. 重複】 重複行数: 1 ❌ 【4. データ型】 user_id: int64 age: float64 price: int64 name: object 【5. 数値カラムの統計】 min max mean std user_id 1.0 4.0 2.40 1.14 age 25.0 35.0 29.50 4.20 price 1000.0 2500.0 1700.00 547.72 ============================================================

🔧 4. Great Expectations入門

4-1. Great Expectationsとは?

Great Expectationsは、データ検証を自動化するPythonライブラリです。
100種類以上の検証ルール(Expectation)が用意されており、複雑な検証も簡単に定義できます。

💡 Great Expectationsのメリット
  • 自動化:検証ルールを一度定義すれば、毎回自動実行
  • ドキュメント化:検証ルールが自己文書化される
  • HTMLレポート:見やすいレポートを自動生成
  • CI/CD統合:パイプラインに組み込める
  • 豊富な検証ルール:100種類以上のExpectation

4-2. インストールと基本的な使い方

# インストール pip install great_expectations
# ===== Great Expectationsの基本的な使い方 ===== import pandas as pd import great_expectations as gx # データ作成 df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 4, 5], ‘age’: [25, 30, 28, 35, 40], ‘email’: [‘a@ex.com’, ‘b@ex.com’, ‘c@ex.com’, ‘d@ex.com’, ‘e@ex.com’] }) # コンテキストを作成(一時的なもの) context = gx.get_context() # DataFrameをデータソースとして追加 datasource = context.sources.add_pandas(“pandas_datasource”) data_asset = datasource.add_dataframe_asset(name=”my_data”) batch_request = data_asset.build_batch_request(dataframe=df) # Validatorを取得(検証器) validator = context.get_validator(batch_request=batch_request) # 検証ルールを定義して実行 print(“=== 検証実行 ===”) # カラムの存在チェック result1 = validator.expect_column_to_exist(“user_id”) print(f”user_idが存在: {result1.success}”) # NULL値がないことを確認 result2 = validator.expect_column_values_to_not_be_null(“user_id”) print(f”user_idにNULLなし: {result2.success}”) # 範囲チェック result3 = validator.expect_column_values_to_be_between(“age”, min_value=0, max_value=120) print(f”ageが0-120の範囲内: {result3.success}”) # 全体の検証実行 results = validator.validate() print(f”\n=== 総合結果 ===”) print(f”成功: {‘✅’ if results.success else ‘❌’}”)
【実行結果】 === 検証実行 === user_idが存在: True user_idにNULLなし: True ageが0-120の範囲内: True === 総合結果 === 成功: ✅

4-3. よく使うExpectation一覧

代表的なExpectation
Expectation 説明
expect_column_to_exist カラムが存在することを確認
expect_column_values_to_not_be_null NULLがないことを確認
expect_column_values_to_be_between 値が指定範囲内であることを確認
expect_column_values_to_be_unique 値が一意であることを確認
expect_column_values_to_be_in_set 値が指定した集合に含まれることを確認
expect_column_values_to_match_regex 正規表現にマッチすることを確認
expect_column_values_to_be_of_type データ型が一致することを確認
expect_table_row_count_to_be_between 行数が指定範囲内であることを確認
✅ Great Expectationsの学習ポイント

Great Expectationsは高機能ですが、学習コストも高いです。
まずは自作の検証関数で基本を理解してから、
本番環境で必要になったらGreat Expectationsを導入することをお勧めします。

🏋️ 5. 実践演習:総合的なデータ品質チェック

5-1. 課題:包括的な検証システムの構築

設定ファイルに基づいて、スキーマ・欠損値・範囲・重複のすべてをチェックする検証システムを構築します。

# ===== 完全な品質チェックシステム ===== import pandas as pd import numpy as np from datetime import datetime def comprehensive_data_validation(df, config): “”” 包括的なデータ検証を実行 Args: df: 検証するDataFrame config: 検証設定(辞書) – schema: {カラム名: データ型} – required_columns: [必須カラムのリスト] – ranges: {カラム名: (最小値, 最大値)} – unique_columns: [一意であるべきカラムのリスト] Returns: dict: 検証結果 “”” results = { ‘timestamp’: datetime.now().strftime(‘%Y-%m-%d %H:%M:%S’), ‘total_rows’: len(df), ‘total_columns’: len(df.columns), ‘checks’: [], ‘passed’: 0, ‘failed’: 0 } print(“=” * 60) print(“データ品質検証レポート”) print(“=” * 60) print(f”実行日時: {results[‘timestamp’]}”) print(f”行数: {results[‘total_rows’]:,}”) print(f”列数: {results[‘total_columns’]}”) # 1. スキーマチェック print(“\n【1. スキーマチェック】”) if ‘schema’ in config: for col, expected_dtype in config[‘schema’].items(): if col not in df.columns: print(f” ❌ カラム ‘{col}’ が存在しません”) results[‘failed’] += 1 elif str(df[col].dtype) != expected_dtype: print(f” ❌ ‘{col}’ の型: {df[col].dtype} (期待: {expected_dtype})”) results[‘failed’] += 1 else: print(f” ✅ ‘{col}’ OK ({expected_dtype})”) results[‘passed’] += 1 # 2. 欠損値チェック print(“\n【2. 欠損値チェック】”) if ‘required_columns’ in config: for col in config[‘required_columns’]: if col in df.columns: null_count = df[col].isnull().sum() if null_count > 0: print(f” ❌ ‘{col}’ に欠損値: {null_count}件 ({null_count/len(df)*100:.1f}%)”) results[‘failed’] += 1 else: print(f” ✅ ‘{col}’ 欠損値なし”) results[‘passed’] += 1 # 3. 範囲チェック print(“\n【3. 範囲チェック】”) if ‘ranges’ in config: for col, (min_val, max_val) in config[‘ranges’].items(): if col in df.columns: invalid = df[(df[col] < min_val) | (df[col] > max_val)] invalid_count = len(invalid) if invalid_count > 0: print(f” ❌ ‘{col}’ が範囲外: {invalid_count}件 ({min_val}〜{max_val})”) results[‘failed’] += 1 else: print(f” ✅ ‘{col}’ 範囲内 ({min_val}〜{max_val})”) results[‘passed’] += 1 # 4. 重複チェック print(“\n【4. 重複チェック】”) if ‘unique_columns’ in config: for col in config[‘unique_columns’]: if col in df.columns: dup_count = df[col].duplicated().sum() if dup_count > 0: print(f” ❌ ‘{col}’ に重複: {dup_count}件”) results[‘failed’] += 1 else: print(f” ✅ ‘{col}’ 重複なし”) results[‘passed’] += 1 # サマリー print(“\n” + “=” * 60) print(“検証サマリー”) print(“=” * 60) total_checks = results[‘passed’] + results[‘failed’] print(f”チェック総数: {total_checks}”) print(f”成功: {results[‘passed’]} ({results[‘passed’]/total_checks*100:.0f}%)”) print(f”失敗: {results[‘failed’]} ({results[‘failed’]/total_checks*100:.0f}%)”) overall_success = results[‘failed’] == 0 print(f”\n総合結果: {‘✅ 合格’ if overall_success else ‘❌ 不合格’}”) results[‘overall_success’] = overall_success return results # ========== 使用例 ========== # テストデータ(意図的に問題を含む) df = pd.DataFrame({ ‘user_id’: [1, 2, 3, 2, 4], # 重複あり ‘name’: [‘山田’, np.nan, ‘鈴木’, ‘佐藤’, ‘田中’], # 欠損値あり ‘age’: [25, 30, -5, 28, 35], # 範囲外あり ‘email’: [‘a@ex.com’, ‘b@ex.com’, ‘c@ex.com’, ‘d@ex.com’, ‘e@ex.com’] }) # 検証設定 validation_config = { ‘schema’: { ‘user_id’: ‘int64’, ‘name’: ‘object’, ‘age’: ‘int64’, ‘email’: ‘object’ }, ‘required_columns’: [‘user_id’, ‘name’, ‘email’], ‘ranges’: { ‘age’: (0, 120) }, ‘unique_columns’: [‘user_id’, ‘email’] } # 検証実行 results = comprehensive_data_validation(df, validation_config)
【実行結果】 ============================================================ データ品質検証レポート ============================================================ 実行日時: 2024-01-15 10:30:45 行数: 5 列数: 4 【1. スキーマチェック】 ✅ ‘user_id’ OK (int64) ✅ ‘name’ OK (object) ✅ ‘age’ OK (int64) ✅ ‘email’ OK (object) 【2. 欠損値チェック】 ✅ ‘user_id’ 欠損値なし ❌ ‘name’ に欠損値: 1件 (20.0%) ✅ ‘email’ 欠損値なし 【3. 範囲チェック】 ❌ ‘age’ が範囲外: 1件 (0〜120) 【4. 重複チェック】 ❌ ‘user_id’ に重複: 1件 ✅ ‘email’ 重複なし ============================================================ 検証サマリー ============================================================ チェック総数: 10 成功: 7 (70%) 失敗: 3 (30%) 総合結果: ❌ 不合格

📝 STEP 12 のまとめ

✅ このステップで学んだこと
  • データ品質の重要性:6つの品質側面(完全性・正確性・一貫性・適時性・妥当性・一意性)
  • スキーマ検証:データ型、カラムの存在チェック
  • 範囲チェック:値が妥当な範囲内かを確認
  • NULLチェック:欠損値の検出
  • 重複チェック:一意性の確認
  • Great Expectations:データ検証の自動化ライブラリ
💡 データ検証のベストプラクティス
  1. ETLの入口で検証:データ取得直後にチェック
  2. ETLの出口で検証:ロード前に最終チェック
  3. 検証ルールを文書化:ルールを明確に定義
  4. エラーをログに記録:問題発生時に追跡可能に
  5. アラートを設定:重大な問題は即座に通知
🎯 次のステップの予告

次のSTEP 13では、「複雑なデータ変換の実践」を学びます。

  • apply()、map()、applymap()の使い分け
  • lambda関数の活用
  • カスタム変換関数の作成

📝 練習問題

問題 1 基礎

DataFrameに’email’カラムが存在するかチェックするコードを書いてください。

【解答例】
if ‘email’ in df.columns: print(“✅ ‘email’ カラムが存在します”) else: print(“❌ ‘email’ カラムが存在しません”)
問題 2 基礎

‘age’カラムに欠損値が何件あるかを確認するコードを書いてください。

【解答例】
null_count = df[‘age’].isnull().sum() print(f”欠損値: {null_count}件”)
問題 3 基礎

‘price’カラムの値が0未満のデータを抽出してください。

【解答例】
invalid_price = df[df[‘price’] < 0] print(invalid_price)
問題 4 基礎

‘user_id’カラムに重複があるかチェックするコードを書いてください。

【解答例】
dup_count = df[‘user_id’].duplicated().sum() if dup_count > 0: print(f”❌ 重複あり: {dup_count}件”) else: print(“✅ 重複なし”)
問題 5 応用

‘age’カラムが0〜120の範囲内かチェックし、範囲外のデータがあれば表示してください。

【解答例】
invalid_age = df[(df[‘age’] < 0) | (df['age'] > 120)] if len(invalid_age) > 0: print(f”❌ 範囲外のデータ: {len(invalid_age)}件”) print(invalid_age) else: print(“✅ すべて範囲内”)
問題 6 応用

DataFrameのデータ型が期待通りかチェックする関数を書いてください。

【解答例】
def check_dtype(df, col, expected_dtype): actual_dtype = str(df[col].dtype) if actual_dtype == expected_dtype: print(f”✅ ‘{col}’ の型は {expected_dtype} で正しい”) return True else: print(f”❌ ‘{col}’ の型は {actual_dtype} (期待: {expected_dtype})”) return False # 使用例 check_dtype(df, ‘age’, ‘int64’)
問題 7 応用

全カラムの欠損値サマリー(カラム名、欠損数、欠損率)を表示するコードを書いてください。

【解答例】
null_counts = df.isnull().sum() null_pct = (null_counts / len(df) * 100).round(2) null_summary = pd.DataFrame({ ‘欠損数’: null_counts, ‘欠損率(%)’: null_pct }) print(null_summary[null_summary[‘欠損数’] > 0])
問題 8 応用

‘email’カラムがメールアドレスの形式(@を含む)かチェックするコードを書いてください。

【解答例】
# @を含まないメールアドレスを検出 invalid_email = df[~df[‘email’].str.contains(‘@’, na=False)] if len(invalid_email) > 0: print(f”❌ 不正なメールアドレス: {len(invalid_email)}件”) print(invalid_email) else: print(“✅ すべて有効な形式”)
問題 9 発展

以下のチェックをすべて行う検証関数を作成してください:
① 必須カラムの存在チェック
② 必須カラムの欠損値チェック
③ 結果をTrue/Falseで返す

【解答例】
def validate_required_columns(df, required_columns): “””必須カラムの存在と欠損値をチェック””” is_valid = True for col in required_columns: # 存在チェック if col not in df.columns: print(f”❌ カラム ‘{col}’ が存在しません”) is_valid = False continue # 欠損値チェック null_count = df[col].isnull().sum() if null_count > 0: print(f”❌ ‘{col}’ に欠損値: {null_count}件”) is_valid = False else: print(f”✅ ‘{col}’ OK”) return is_valid # 使用例 result = validate_required_columns(df, [‘user_id’, ‘name’, ‘email’])
問題 10 発展

以下の情報を含むデータ品質レポートを作成する関数を書いてください:
① 基本情報(行数、列数)
② 各カラムの欠損値数と欠損率
③ 重複行数
④ 数値カラムの最小値・最大値

【解答例】
def create_quality_report(df): “””データ品質レポートを作成””” print(“=” * 50) print(“データ品質レポート”) print(“=” * 50) # ① 基本情報 print(f”\n【基本情報】”) print(f” 行数: {len(df):,}”) print(f” 列数: {len(df.columns)}”) # ② 欠損値 print(f”\n【欠損値】”) for col in df.columns: null_count = df[col].isnull().sum() null_pct = null_count / len(df) * 100 print(f” {col}: {null_count}件 ({null_pct:.1f}%)”) # ③ 重複 print(f”\n【重複】”) dup_count = df.duplicated().sum() print(f” 重複行数: {dup_count}”) # ④ 数値カラムの範囲 print(f”\n【数値カラムの範囲】”) for col in df.select_dtypes(include=’number’).columns: print(f” {col}: {df[col].min()} 〜 {df[col].max()}”) print(“\n” + “=” * 50) # 使用例 create_quality_report(df)
📝

学習メモ

ETL・データパイプライン構築 - Step 12

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE