82

パンダのデータフレームを行ごとまたは列ごとにシャッフルする簡単で効率的な方法は何ですか? shuffle(df, n, axis=0)つまり、データフレーム、シャッフルの数n、および軸 (axis=0行、axis=1列) を受け取り、何度もシャッフルされたデータフレームのコピーを返す関数を作成する方法nです。

編集:データフレームの行/列ラベルを破壊せずにこれを行うことが重要です。シャッフルdf.indexすると、すべての情報が失われます。df行の順序または列の順序が異なることを除いて、結果を元と同じにしたい。

Edit2 :私の質問は不明確でした。行をシャッフルするとは、各行を個別にシャッフルすることを意味します。したがって、 と の 2 つの列がある場合ab各行を個別にシャッフルして、各行を全体として並べ替えた場合のように、 と の間aに同じ関連付けを持たないようにします。b何かのようなもの:

for 1...n:
  for each col in df: shuffle column
return new_df

しかし、うまくいけば、単純なループよりも効率的です。これは私にはうまくいきません:

def shuffle(df, n, axis=0):
        shuffled_df = df.copy()
        for k in range(n):
            shuffled_df.apply(np.random.shuffle(shuffled_df.values),axis=axis)
        return shuffled_df

df = pandas.DataFrame({'A':range(10), 'B':range(10)})
shuffle(df, 5)
4

10 に答える 10

226

numpy のrandom.permuation関数を使用します。

In [1]: df = pd.DataFrame({'A':range(10), 'B':range(10)})

In [2]: df
Out[2]:
   A  B
0  0  0
1  1  1
2  2  2
3  3  3
4  4  4
5  5  5
6  6  6
7  7  7
8  8  8
9  9  9


In [3]: df.reindex(np.random.permutation(df.index))
Out[3]:
   A  B
0  0  0
5  5  5
6  6  6
3  3  3
8  8  8
7  7  7
9  9  9
1  1  1
2  2  2
4  4  4
于 2013-04-02T19:09:05.050 に答える
42
In [16]: def shuffle(df, n=1, axis=0):     
    ...:     df = df.copy()
    ...:     for _ in range(n):
    ...:         df.apply(np.random.shuffle, axis=axis)
    ...:     return df
    ...:     

In [17]: df = pd.DataFrame({'A':range(10), 'B':range(10)})

In [18]: shuffle(df)

In [19]: df
Out[19]: 
   A  B
0  8  5
1  1  7
2  7  3
3  6  2
4  3  4
5  0  1
6  9  0
7  4  6
8  2  8
9  5  9
于 2013-04-02T19:10:49.460 に答える
9

パンダでの簡単な解決策は、sample各列でメソッドを個別に使用することです。apply各列を反復するために使用します。

df = pd.DataFrame({'a':[1,2,3,4,5,6], 'b':[1,2,3,4,5,6]})
df

   a  b
0  1  1
1  2  2
2  3  3
3  4  4
4  5  5
5  6  6

df.apply(lambda x: x.sample(frac=1).values)

   a  b
0  4  2
1  1  6
2  6  5
3  5  3
4  2  4
5  3  1

Series ではなく numpy 配列を返すように使用する必要があります.value。そうしないと、返された Series が元の DataFrame に揃えられ、何も変更されません。

df.apply(lambda x: x.sample(frac=1))

   a  b
0  1  1
1  2  2
2  3  3
3  4  4
4  5  5
5  6  6
于 2017-11-04T15:40:37.797 に答える
4

@root の回答を少し変更し、生の値を直接使用することにしました。もちろん、これは派手なインデックス作成を行う能力を失うことを意味しますが、データをシャッフルするだけでは完全に機能します。

In [1]: import numpy

In [2]: import pandas

In [3]: df = pandas.DataFrame({"A": range(10), "B": range(10)})    

In [4]: %timeit df.apply(numpy.random.shuffle, axis=0)
1000 loops, best of 3: 406 µs per loop

In [5]: %%timeit
   ...: for view in numpy.rollaxis(df.values, 1):
   ...:     numpy.random.shuffle(view)
   ...: 
10000 loops, best of 3: 22.8 µs per loop

In [6]: %timeit df.apply(numpy.random.shuffle, axis=1)
1000 loops, best of 3: 746 µs per loop

In [7]: %%timeit                                      
for view in numpy.rollaxis(df.values, 0):
    numpy.random.shuffle(view)
   ...: 
10000 loops, best of 3: 23.4 µs per loop

指定された軸を最初の次元にnumpy.rollaxis持ってきて、残りの次元で配列を繰り返しましょう。最初の次元のビューにシャッフルを適用します。

In [8]: numpy.rollaxis(df, 0).shape
Out[8]: (10, 2) # we can iterate over 10 arrays with shape (2,) (rows)

In [9]: numpy.rollaxis(df, 1).shape
Out[9]: (2, 10) # we can iterate over 2 arrays with shape (10,) (columns)

次に、最終的な関数はトリックを使用して、関数を軸に適用するという期待に沿った結果をもたらします。

def shuffle(df, n=1, axis=0):     
    df = df.copy()
    axis = int(not axis) # pandas.DataFrame is always 2D
    for _ in range(n):
        for view in numpy.rollaxis(df.values, axis):
            numpy.random.shuffle(view)
    return df
于 2014-02-01T20:08:28.517 に答える
3

これは、インデックスをシャッフルしたい場合により便利です。

def shuffle(df):
    index = list(df.index)
    random.shuffle(index)
    df = df.ix[index]
    df.reset_index()
    return df

新しいインデックスを使用して新しい df を選択し、それらをリセットします。

于 2014-08-14T23:48:12.780 に答える