【Pandasデータ操作】DataFrame・Seriesの行をランダムにシャッフルする方法


 

データ分析や機械学習の準備段階で、データセットの順序が結果に影響を与えないよう、**行をランダムに並べ替える(シャッフルする)**必要がある場面はよくあります。例えば、機械学習モデルの訓練データを作成する際、特定の順序で並んだデータによってモデルが偏った学習をしてしまうことを防ぐためにシャッフルを行います。Pandasを使えば、DataFrameやSeriesの行を簡単かつ効率的にシャッフルすることができます。この記事では、Pandasでデータをシャッフルする主要な方法を、短いサンプルコードと丁寧な解説を交えてご紹介します。


 

なぜDataFrame/Seriesの行をシャッフルするのか?

 

DataFrameやSeriesの行をシャッフルする主な理由は以下の通りです。

  • データの公平性確保: 特に時系列データのように順序に意味があるデータの場合、意図しないパターンやトレンドが学習されるのを防ぎます。

  • 機械学習の準備: 訓練データとテストデータを分割する前や、ミニバッチ学習を行う前にデータをシャッフルすることで、モデルが特定のデータ順序に過剰に適合する(過学習)のを防ぎ、汎化性能を高めます。

  • A/Bテストなどの実験: 実験グループにデータを割り当てる際に、偏りなくランダムに割り振るために使われます。

  • 探索的データ分析: 大規模なデータセットの全体的な特徴をランダムに確認したい場合に、特定の順序の影響を排除できます。


 

sample()メソッドでDataFrameの行をシャッフルする

 

PandasでDataFrameの行をシャッフルする最もシンプルで推奨される方法は、sample()メソッドを使用することです。

 

全ての行をランダムにシャッフルする

 

sample()メソッドにfrac=1(データの全量)とrandom_state(再現性のため)を指定することで、DataFrameの全行をランダムに並べ替えることができます。

Python
 
import pandas as pd
import numpy as np

# サンプルDataFrameの作成
df = pd.DataFrame({
    'ID': range(1, 6),
    'Value': np.random.randint(1, 100, 5),
    'Category': ['A', 'B', 'C', 'A', 'B']
})
print("オリジナルDataFrame:\n", df)

# 全ての行をランダムにシャッフル
# frac=1で全行を選択
# random_stateで再現性を確保(任意の値でOK)
df_shuffled = df.sample(frac=1, random_state=42)
print("\nシャッフル後DataFrame:\n", df_shuffled)

解説:

  1. frac=1: DataFrameの全行(100%)をサンプリング対象とします。これにより、元のDataFrameの全ての行がシャッフルされます。

  2. random_state=42: random_stateに整数値を指定することで、何度実行しても同じシャッフル結果が得られます。これは、機械学習の実験などで再現性を保証するために非常に重要です。テスト時やデバッグ時には固定し、本番環境で真のランダム性が必要な場合は指定しないか、動的に生成される値を使用します。

 

インデックスをリセットする

 

シャッフルすると元のインデックスの順序がバラバラになります。多くの場合、シャッフル後にインデックスを振り直す方が便利です。

Python
 
# シャッフル後、インデックスをリセット
df_shuffled_reset_index = df.sample(frac=1, random_state=42).reset_index(drop=True)
print("\nシャッフル後、インデックスをリセットしたDataFrame:\n", df_shuffled_reset_index)

解説:

  • .reset_index(): 新しい連番のインデックスを振り直します。

  • drop=True: 元のインデックスが新しい列として追加されるのを防ぎます(元のインデックスは破棄されます)。


 

Seriesの行をシャッフルする

 

DataFrameと同様に、Seriesの要素(行)もsample()メソッドでシャッフルできます。

Python
 
# サンプルSeriesの作成
s = pd.Series([10, 20, 30, 40, 50])
print("\nオリジナルSeries:\n", s)

# Seriesの全ての要素をランダムにシャッフル
s_shuffled = s.sample(frac=1, random_state=42)
print("\nシャッフル後Series:\n", s_shuffled)

# シャッフル後、インデックスをリセット
s_shuffled_reset_index = s.sample(frac=1, random_state=42).reset_index(drop=True)
print("\nシャッフル後、インデックスをリセットしたSeries:\n", s_shuffled_reset_index)

解説:

Seriesに対しても、DataFrameと同じようにsample(frac=1)を適用し、必要に応じてreset_index(drop=True)でインデックスを振り直します。


 

ilocnumpy.random.permutationを使う(より低レベルな制御)

 

sample()が最も簡単ですが、Pandasのインデックス参照機能(iloc)とNumPyのランダムパーミュテーションを組み合わせてシャッフルすることも可能です。これは、より低レベルでインデックスの順序を制御したい場合などに使えますが、通常はsample()で十分です。

Python
 
import numpy as np

# インデックスの順序をランダムに生成
shuffled_indices = np.random.permutation(df.index)
print("\nシャッフルされたインデックス:\n", shuffled_indices)

# 生成したインデックスの順序でDataFrameを並べ替える
df_shuffled_iloc = df.loc[shuffled_indices]
print("\nilocとpermutationでシャッフル後DataFrame:\n", df_shuffled_iloc)

解説:

  1. np.random.permutation(df.index): DataFrameのインデックスをランダムに並べ替えたNumPy配列を生成します。

  2. df.loc[shuffled_indices]: 生成されたランダムなインデックスの順序に従って、DataFrameの行を再配置します。


 

まとめ

 

PandasでDataFrameやSeriesの行をランダムにシャッフルする方法は、データ分析や機械学習の前処理において非常に重要なテクニックです。最も推奨される方法は、**sample(frac=1, random_state=...)**メソッドを使用することです。これにより、データの公平性を保ち、モデルの過学習を防ぎ、実験の再現性を確保することができます。シャッフル後に必要であれば、reset_index(drop=True)でインデックスを振り直すことも忘れないようにしましょう。これらのシャッフル機能を使いこなして、より堅牢で信頼性の高いデータ分析ワークフローを構築しましょう。