1. ホーム
  2. python

[解決済み] DataFrameの行をシャッフルする

2022-03-14 07:25:07

質問

以下のようなDataFrameがあります。

    Col1  Col2  Col3  Type
0      1     2     3     1
1      4     5     6     1
...
20     7     8     9     2
21    10    11    12     2
...
45    13    14    15     3
46    16    17    18     3
...

DataFrameはcsvファイルから読み込まれます。すべての行は Type 1の行が上になり、その後に Type 2の行、その後に Type 3など。

DataFrameの行の順番をシャッフルして、すべての Type が混在している。考えられる結果は以下の通りです。

    Col1  Col2  Col3  Type
0      7     8     9     2
1     13    14    15     3
...
20     1     2     3     1
21    10    11    12     2
...
45     4     5     6     1
46    16    17    18     3
...

どうすれば実現できるのでしょうか?

どのように解決するのですか?

Pandasでこれを行うイディオム的な方法は .sample メソッドを使用して、すべての行を置換せずにサンプリングします。

df.sample(frac=1)

frac キーワード引数は、ランダムサンプルで返す行の割合を指定します。 frac=1 は、すべての行を(ランダムな順序で)返すことを意味します。


データフレームをインプレースでシャッフルし、インデックスをリセットしたい場合は、以下のようにします。

df = df.sample(frac=1).reset_index(drop=True)

ここで drop=True を防ぐことができます。 .reset_index は、古いインデックスエントリを含むカラムを作成しないようにします。

フォローアップの注意点 上記の操作のように見えないかもしれませんが インプレース Python/pandasは賢いので、シャッフルされたオブジェクトのために別のmallocをすることはありません。つまり、たとえ 参照 オブジェクトが変更されました(つまり id(df_old) とは異なります。 id(df_new) ) 、基礎となるCのオブジェクトはまだ同じです。これが本当にそうであることを示すために、簡単なメモリプロファイラを実行することができます。

$ python3 -m memory_profiler .\test.py
Filename: .\test.py

Line #    Mem usage    Increment   Line Contents
================================================
     5     68.5 MiB     68.5 MiB   @profile
     6                             def shuffle():
     7    847.8 MiB    779.3 MiB       df = pd.DataFrame(np.random.randn(100, 1000000))
     8    847.9 MiB      0.1 MiB       df = df.sample(frac=1).reset_index(drop=True)