Pandas sample()でランダムサンプリング・抽出する方法【完全ガイド】

 

データ分析において、大量のデータから一部をランダムに抽出することは頻繁にあります。Pandasのsample()メソッドを使えば、DataFrameやSeriesから行や列を簡単にランダムサンプリングできます。この記事では、sample()メソッドの使い方を基本から応用まで、実践的なサンプルコードとともに詳しく解説します。

基本的な準備とサンプルデータの作成

まず、この記事で使用するサンプルDataFrameを作成しましょう。

import pandas as pd
import numpy as np

# サンプルデータの作成
np.random.seed(42)  # 再現性のため
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry'],
    'age': [25, 30, 35, 28, 22, 31, 27, 33],
    'salary': [50000, 60000, 75000, 55000, 45000, 70000, 52000, 80000],
    'department': ['IT', 'HR', 'IT', 'Finance', 'HR', 'IT', 'Finance', 'IT']
})

print(df)

このコードを実行すると、8行4列のDataFrameが作成されます:

      name  age  salary department
0    Alice   25   50000         IT
1      Bob   30   60000         HR
2  Charlie   35   75000         IT
3    David   28   55000    Finance
4      Eve   22   45000         HR
5    Frank   31   70000         IT
6    Grace   27   52000    Finance
7    Henry   33   80000         IT

基本的な行のランダムサンプリング

指定した件数をランダム抽出

最もシンプルな使用方法は、指定した件数の行をランダムに抽出することです。

# 3行をランダムに抽出
sample_3 = df.sample(n=3)
print(sample_3)

nパラメータで抽出したい行数を指定します。毎回実行するたびに異なる結果が得られます。

割合を指定してランダム抽出

データ全体の一定割合をサンプリングしたい場合は、fracパラメータを使用します。

# 全体の50%をランダムに抽出
sample_50pct = df.sample(frac=0.5)
print(sample_50pct)
print(f"抽出件数: {len(sample_50pct)}")

frac=0.5は全体の50%を意味します。8行のデータなら4行が抽出されます。

ランダムシードの設定と再現性

データサイエンスでは、結果の再現性が重要です。random_stateパラメータを使って、同じランダムサンプリング結果を得ることができます。

# 再現可能なランダムサンプリング
sample1 = df.sample(n=3, random_state=42)
sample2 = df.sample(n=3, random_state=42)

print("サンプル1:")
print(sample1)
print("\nサンプル2:")
print(sample2)
print(f"同じ結果か: {sample1.equals(sample2)}")

random_stateに同じ値を設定すると、常に同じランダムサンプリング結果が得られます。

復元抽出(重複を許可)

デフォルトではsample()は復元なし抽出(同じ行は一度しか選ばれない)ですが、replace=Trueを設定すると復元あり抽出(重複を許可)が可能です。

# 復元ありでサンプリング(重複を許可)
sample_with_replacement = df.sample(n=10, replace=True, random_state=42)
print(sample_with_replacement)
print(f"重複確認: {sample_with_replacement.index.duplicated().any()}")

これにより、元のデータよりも多くの行を抽出したり、同じ行を複数回選択したりできます。

重み付きランダムサンプリング

特定の条件に基づいて、行が選ばれる確率を変更することもできます。

# 給与に基づいた重み付きサンプリング
weights = df['salary'] / df['salary'].sum()  # 給与の割合を重みとする
weighted_sample = df.sample(n=3, weights=weights, random_state=42)
print(weighted_sample)

この例では、給与が高い人ほど選ばれやすくなります。weightsパラメータには各行の重みを指定します。

列のランダムサンプリング

行だけでなく、列もランダムに抽出できます。axis=1またはaxis='columns'を指定します。

# 2列をランダムに抽出
sample_columns = df.sample(n=2, axis=1, random_state=42)
print(sample_columns)

この機能は、多数の特徴量から一部をランダムに選択する特徴選択に役立ちます。

条件付きサンプリング

特定の条件を満たすデータからランダムサンプリングを行う方法です。

# IT部門のデータのみからサンプリング
it_employees = df[df['department'] == 'IT']
it_sample = it_employees.sample(n=2, random_state=42)
print("IT部門からのサンプル:")
print(it_sample)

まずデータをフィルタリングしてから、そのサブセットからサンプリングを行います。

グループ別サンプリング

各グループから同じ件数をサンプリングしたい場合は、groupby()と組み合わせます。

# 各部門から1人ずつサンプリング
group_sample = df.groupby('department').sample(n=1, random_state=42)
print("各部門から1人ずつ:")
print(group_sample)

この方法により、偏りのないサンプリングが可能になります。

実践的な応用例

学習データとテストデータの分割

機械学習でよく使われるデータ分割の例です。

# 学習用70%、テスト用30%に分割
train_data = df.sample(frac=0.7, random_state=42)
test_data = df.drop(train_data.index)

print(f"学習データ: {len(train_data)}件")
print(f"テストデータ: {len(test_data)}件")

大量データの preview用サンプル

大きなデータセットから一部を抽出して内容を確認する場合:

# 大量データの場合のサンプル確認
def preview_data(dataframe, sample_size=5):
    """データの概要確認用サンプル"""
    if len(dataframe) > sample_size:
        sample = dataframe.sample(n=sample_size)
        print(f"全{len(dataframe)}件中{sample_size}件のサンプル:")
        return sample
    else:
        return dataframe

preview_sample = preview_data(df, 3)
print(preview_sample)

層化サンプリング

各カテゴリから同じ割合でサンプリングする層化サンプリング:

# 各部門から同じ割合でサンプリング
def stratified_sample(df, strata_col, frac=0.5, random_state=None):
    """層化サンプリング"""
    return df.groupby(strata_col).sample(frac=frac, random_state=random_state)

stratified = stratified_sample(df, 'department', frac=0.5, random_state=42)
print("層化サンプリング結果:")
print(stratified)

エラーの回避とベストプラクティス

サンプルサイズが元データより大きい場合

復元なしサンプリングで、要求するサンプル数が元データより大きい場合のエラー対処:

def safe_sample(df, n, replace=False, random_state=None):
    """安全なサンプリング"""
    if n > len(df) and not replace:
        print(f"警告: 要求サイズ{n}が元データサイズ{len(df)}より大きいため、全データを返します")
        return df
    return df.sample(n=n, replace=replace, random_state=random_state)

# 使用例
safe_result = safe_sample(df, n=20, replace=False)
print(f"結果件数: {len(safe_result)}")

パフォーマンスの考慮事項

大量データの場合のパフォーマンス向上のコツ:

# 大量データの場合は、まず必要な列だけ選択してからサンプリング
# 効率的な方法
needed_columns = ['name', 'age']
efficient_sample = df[needed_columns].sample(n=3, random_state=42)
print(efficient_sample)

sample()メソッドのパラメータ一覧

sample()メソッドの主要パラメータをまとめます:

# 全パラメータの使用例
comprehensive_sample = df.sample(
    n=3,              # 抽出件数
    frac=None,        # 抽出割合(nと排他)
    replace=False,    # 復元抽出の可否
    weights=None,     # 重み
    random_state=42,  # ランダムシード
    axis=0           # 0:行, 1:列
)
print(comprehensive_sample)

まとめ

Pandasのsample()メソッドは、データ分析において非常に強力なランダムサンプリングツールです。この記事で紹介した手法を活用することで、効率的なデータ分析が可能になります。

主なポイント:

  • nで件数、fracで割合を指定してサンプリング
  • random_stateで再現可能な結果を確保
  • replace=Trueで復元ありサンプリング
  • weightsで重み付きサンプリング
  • groupby()と組み合わせてグループ別サンプリング

これらのテクニックを使い分けることで、様々なサンプリングニーズに対応できるでしょう。データの特性や分析目的に応じて、最適なサンプリング手法を選択してください。