Shuffle DataFrame rows
j'ai la base de données suivante:
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
...
la base de données est lue à partir d'un fichier csv. Toutes les lignes qui ont Type
1 sont en tête, suivis par les lignes avec Type
2, suivie par les lignes avec Type
3, etc.
je voudrais mélanger les lignes de la base de données, de sorte que tous les Type
sont 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 le montre le résultat, l'ordre des les lignes sont mélangées, mais les colonnes restent les mêmes. Je ne sais pas si je vais expliquer cela clairement. Prévenez-moi si Je ne le fais pas.
Comment puis-je y parvenir?
7 réponses
la façon la plus idiomatique de faire cela avec pandas est d'utiliser la méthode .sample
de votre dataframe, i.e.
df.sample(frac=1)
l'argument de mot-clé frac
spécifie la fraction de lignes à retourner dans l'échantillon aléatoire, donc frac=1
signifie retourner toutes les lignes (dans l'ordre aléatoire).
Note: si vous souhaitez mélanger votre dataframe en place et réinitialiser l'index, vous pouvez faire par exemple
df = df.sample(frac=1).reset_index(drop=True)
ici, en spécifiant drop=True
empêche .reset_index
de créer une colonne contenant les anciennes entrées de l'index.
vous pouvez simplement utiliser sklearn pour ce
from sklearn.utils import shuffle
df = shuffle(df)
vous pouvez mélanger les lignes d'une base de données en indexant avec un index mélangé. Pour cela, vous pouvez par exemple utiliser np.random.permutation
(mais np.random.choice
est également 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 voulez garder 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)
TL;DR : np.random.shuffle(ndarray)
peut faire le travail.
Donc, dans votre cas
np.random.shuffle(DataFrame.values)
D'après ce que j'ai compris, DataFrame, sous le capot, utilise NumPy ndarray comme support de données. Vous pouvez vérifier à partir de code source DataFrame .
Donc, si vous utilisez np.random.shuffle()
, il mélangerait le tableau le long du premier axe d'un tableau multidimensionnel. Mais les colonnes-sage reste le même.
certaines limites sont indiquées ci-après.
- aucune. Dans le cas où vous souhaitez conserver une copie de l'objet original, vous devez le faire avant de passer à la fonction.
-
sklearn.utils.shuffle()
l'utilisateur tj89 suggéré, peut désignerrandom_state
avec une autre option pour contrôler la sortie. Tu peux vouloir ça pour dev purpose.
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
DataFrame
df = sklearn.utils.shuffle(df)
0.3183923360193148 sec. 3x plus rapide
np.random.shuffle(df.values)', setup=setup, number=1000)
0,9357550159329548 sec
Conclusion: utilisation
sklearn.utils.shuffle()
, si possible.
code utilisé
setup = '''
import numpy as np
import pandas as pd
from sklearn.utils import shuffle
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)
(Je n'ai pas assez de réputation pour commenter ceci sur le post supérieur, donc j'espère que quelqu'un d'autre peut faire cela pour moi.) on s'est inquiété du fait que la première méthode:
df.sample(frac=1)
fait une copie profonde ou vient de changer la base de données. J'ai lancé 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 étaient:
0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70
qui signifie que la méthode est et non retournant le même objet, comme il était suggéré dans le dernier commentaire. Ainsi, cette méthode fait en effet une copie mélangée 1519130920".
AFAIK la solution la plus simple est:
df_shuffled = df.reindex(np.random.permutation(df.index))
mélanger la base de données pandas en prenant un tableau échantillon dans ce cas index et randomiser son ordre puis définir le tableau comme un indice de la base de données. Maintenant, triez la base de données selon l'indice.
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 base de données à la place de la mienne dans le code ci-dessus .