次のような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ファイルから読み込まれています.タイプ」が1であるすべての行が先頭にあり,次に「タイプ」が2である行が続き,さらに「タイプ」が3である行が続きます.
データフレームの行の順番をシャッフルして,すべてのタイプ
が混在するようにしたいと思います。考えられる結果は次のようになります。
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
メソッドを使用することです。
``python
df.sample(frac=1)
frac`キーワード引数はランダムサンプルで返す行の割合を指定します。
----------
**注意:**。
もし、データフレームをその場でシャッフルしてインデックスをリセットしたい場合は、以下のようにします。
``python
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
ファイル名: .httest.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)
シャッフルされたインデックスでインデックスを作成することで、データフレームの行をシャッフルすることができます。これには、例えば np.random.permutation
が使えます(ただし、np.random.choice
も使えます)。
In [12]: df = pd.read_csv(StringIO(s), sep="\s+")
In [13]: df
Out[13]:
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
In [14]: df.iloc[np.random.permutation(len(df))]
Out[14]:
Col1 Col2 Col3 Type
46 16 17 18 3
45 13 14 15 3
20 7 8 9 2
0 1 2 3 1
1 4 5 6 1
21 10 11 12 2
今回の例のように、インデックスに1、2、...、nの番号をつけておきたい場合は、単純にインデックスをリセットします。df_shuffled.reset_index(drop=True)