Eu tenho o seguinte 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
...
O DataFrame é lido a partir de um arquivo csv. Todas as linhas que têm Type
1 estão no topo, seguidas pelas linhas com Type
2, seguidas pelas linhas com Type
3, etc.
Eu gostaria de embaralhar a ordem das linhas DataFrame's, para que todos os Type
's sejam misturados. Um possível resultado poderia ser:
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
...
Como posso conseguir isto?
A maneira idiomática de fazer isso com pandas é utilizar o método `.sample' do seu dataframe, ou seja
df.sample(frac=1)
O argumento frac
especifica a fração de linhas a retornar na amostra aleatória, então frac=1
significa retornar todas as linhas (em ordem aleatória).
Nota: Se você deseja embaralhar o seu dataframe no local e reiniciar o índice, você pode fazer, por exemplo
df = df.sample(frac=1).reset_index(drop=True)
Aqui, especificar drop=True
evita que .reset_index
crie uma coluna contendo as entradas de índice antigas.
Nota de acompanhamento: Embora possa não parecer que a operação acima seja no lugar, python/pandas é suficientemente inteligente para não fazer outro malloc para o objeto embaralhado. Isto é, mesmo que o objeto referência tenha mudado (ou seja, id(df_old)
não é o mesmo que id(df_new)
), o objeto C subjacente ainda é o mesmo. Para mostrar que este é realmente o caso, você poderia executar um simples profiler de memória:
$ python3 -m memory_profiler .\test.py
Nome do ficheiro: .\t.py
Linha # Utilização de membr. Conteúdo da linha de incrementos
================================================
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)
Você pode embaralhar as linhas de um quadro de dados através da indexação com um índice embaralhado. Para isso, você pode, por exemplo, utilizar np.random.permutation' (mas
np.random.choice' também é uma possibilidade):
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
Se você quiser manter o índice numerado de 1, 2, ..., n como no seu exemplo, você pode simplesmente redefinir o índice: df_shuffled.reset_index(drop=True)