web-dev-qa-db-fra.com

Mélanger les lignes DataFrame

J'ai le DataFrame suivant:

    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
...

Le DataFrame est lu à partir d'un fichier csv. Toutes les lignes qui ont Type 1 sont en haut, suivies des lignes avec Type 2, suivies des lignes avec Type 3, etc.

Je voudrais mélanger les lignes du DataFrame, de sorte que tous les Type soient mélangés. Un résultat possible pourrait être:

    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
...

Comme on peut le voir d'après le résultat, l'ordre des lignes est mélangé, mais les colonnes restent les mêmes. Je ne sais pas si j'explique cela clairement. Faites-moi savoir si je ne le fais pas.

Comment puis-je atteindre cet objectif?

215
JNevens

La façon la plus idiomatique de le faire avec des pandas est d’utiliser la méthode .sample de votre dataframe, c’est-à-dire.

df.sample(frac=1)

L'argument frac indique la fraction de lignes à renvoyer dans l'échantillon aléatoire. frac=1 signifie donc renvoyer toutes les lignes (dans un ordre aléatoire).

Remarque: Si vous souhaitez mélanger votre dataframe sur place et réinitialiser l'index, vous pouvez le faire, par exemple.

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

Ici, spécifier drop=True empêche .reset_index de créer une colonne contenant les anciennes entrées d'index.

460
Kris

Vous pouvez simplement utiliser sklearn pour cela

from sklearn.utils import shuffle
df = shuffle(df)
130
tj89

Vous pouvez mélanger les lignes d'une image en indexant avec un index mélangé. Pour cela, vous pouvez par exemple utiliser np.random.permutation (mais np.random.choice est aussi une possibilité):

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

Si vous souhaitez conserver l'index numéroté de 1, 2, .., n comme dans votre exemple, vous pouvez simplement réinitialiser l'index: df_shuffled.reset_index(drop=True)

47
joris

TL; DR: np.random.shuffle(ndarray) peut faire le travail.
Donc, dans votre cas 

np.random.shuffle(DataFrame.values)

DataFrame, sous le capot, utilise NumPy ndarray en tant que détenteur de données. (Vous pouvez vérifier depuis le code source de DataFrame )

Donc, si vous utilisez np.random.shuffle() , le tableau sera mélangé le long du premier axe d'un tableau multidimensionnel. Mais l'index de la DataFrame reste non brassé.

Cependant, il y a quelques points à considérer. 

  • fonction ne renvoie aucun. Si vous souhaitez conserver une copie de l'objet d'origine, vous devez le faire avant de passer à la fonction.
  • sklearn.utils.shuffle() , comme l’a suggéré l’utilisateur tj89, peut désigner random_state avec une autre option permettant de contrôler la sortie. Vous voudrez peut-être cela à des fins de développement.
  • sklearn.utils.shuffle() est plus rapide. Mais va effacer les informations d'axe (index, colonne) de la DataFrame avec la ndarray qu'il contient.

Résultat de référence

entre sklearn.utils.shuffle() et np.random.shuffle() .

ndarray

nd = sklearn.utils.shuffle(nd)

0,10793248389381915 sec. 8x plus rapide

np.random.shuffle(nd)

0.8897626010002568 sec

Trame de données

df = sklearn.utils.shuffle(df)

0.3183923360193148 sec. 3x plus rapide

np.random.shuffle(df.values)

0.9357550159329548 sec

Conclusion: Si les informations sur l’axe (index, colonne) doivent être mélangées avec ndarray, utilisez sklearn.utils.shuffle() . Sinon, utilisez np.random.shuffle()

code utilisé

import timeit
setup = '''
import numpy as np
import pandas as pd
import sklearn
nd = np.random.random((1000, 100))
df = pd.DataFrame(nd)
'''

timeit.timeit('nd = sklearn.utils.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('df = sklearn.utils.shuffle(df)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(df.values)', setup=setup, number=1000)

pythonanalyse comparative

23
haku

((Je n'ai pas assez de réputation pour commenter cela sur le post le plus haut, j'espère que quelqu'un d'autre pourra le faire pour moi.)} Il y avait un problème qui était soulevé concernant la première méthode: 

df.sample(frac=1)

fait une copie profonde ou vient de changer le dataframe. J'ai couru le code suivant:

print(hex(id(df)))
print(hex(id(df.sample(frac=1))))
print(hex(id(df.sample(frac=1).reset_index(drop=True))))

et mes résultats ont été:

0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70

ce qui signifie que la méthode est pas renvoyer le même objet, comme suggéré dans le dernier commentaire. Donc, cette méthode crée effectivement un mélange copie.

9
NotANumber

Autant que je sache, la solution la plus simple est:

df_shuffled = df.reindex(np.random.permutation(df.index))
3
Ido Cohn

Ce qui est également utile, si vous l'utilisez pour Machine_learning et souhaitez séparer toujours les mêmes données, vous pouvez utiliser:

df.sample(n=len(df), random_state=42)

cela garantit que vous gardez votre choix aléatoire toujours réplicable

0
PV8

mélangez le bloc de données pandas en prenant un exemple de tableau dans ce cas index et aléatoirement son ordre, puis définissez le tableau comme un index du cadre de données. Maintenant, triez le bloc de données en fonction de l'index. Voici votre dataframe mélangé 

import random
df = pd.DataFrame({"a":[1,2,3,4],"b":[5,6,7,8]})
index = [i for i in range(df.shape[0])]
random.shuffle(index)
df.set_index([index]).sort_index()

sortie

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

Insérez votre cadre de données à la place du mien dans le code ci-dessus.

Voici un autre moyen:

df['rnd'] = np.random.Rand(len(df)) df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)

0
soulmachine

La façon la plus simple de faire est le code ci-dessous. (Python)

from sklearn.utils import shuffle
dataFrame = shuffle(dataFrame)

Cela va bouger toutes les colonnes et vous aurez un bon mélange de toutes, de sorte que tous les Type 'soient mélangés

0
Sundeep Pidugu