DataFrame-rijen in willekeurige volgorde afspelen

Ik heb het volgende 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
...

Het DataFrame wordt gelezen uit een csv-bestand. Alle rijen met Type1 staan bovenaan, gevolgd door de rijen met Type2, gevolgd door de rijen met Type3, enz.

Ik wil de volgorde van de rijen van het DataFrame door elkaar halen, zodat alle Type‘s worden gemengd. Een mogelijk resultaat zou kunnen zijn:

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

Hoe kan ik dit bereiken?


Antwoord 1, autoriteit 100%

De idiomatische manier om dit met Panda’s te doen, is door de .samplemethode van uw dataframe om alle rijen te samplen zonder vervanging:

df.sample(frac=1)

Het sleutelwoordargument fracspecificeert de fractie rijen die moet worden geretourneerd in de willekeurige steekproef, dus frac=1betekent dat alle rijen worden geretourneerd (in willekeurige volgorde).


Opmerking:
Als u uw dataframe op zijn plaats wilt shufflen en de index opnieuw wilt instellen, kunt u bijvoorbeeld

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

Hier, door drop=Trueop te geven, voorkomt u dat .reset_indexeen kolom maakt met de oude indexitems.

Vervolgopmerking:hoewel het er misschien niet uitziet alsof de bovenstaande bewerking in-placeis, is python/panda’s slim genoeg om niet nog een malloc te doen voor de geschudde object. Dat wil zeggen, ook al is het referentieobjectgewijzigd (waarmee ik bedoel dat id(df_old)niet hetzelfde is als id(df_new)) , is het onderliggende C-object nog steeds hetzelfde. Om aan te tonen dat dit inderdaad het geval is, kunt u een eenvoudige geheugenprofiler uitvoeren:

$ python3 -m memory_profiler .\test.py
Filename: .\test.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)

Antwoord 2, autoriteit 24%

Je kunt hiervoor gewoon sklearn gebruiken

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

Antwoord 3, autoriteit 6%

U kunt de rijen van een dataframe door elkaar schudden door te indexeren met een geschudde index. Hiervoor kun je bijvoorbeeld np.random.permutationgebruiken (maar np.random.choiceis ook een mogelijkheid):

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

Als u de index genummerd wilt houden van 1, 2, .., N Zoals in uw voorbeeld, kunt u eenvoudig de index opnieuw instellen: df_shuffled.reset_index(drop=True)


Antwoord 4

(Ik heb niet genoeg reputatie om dit op de bovenste post te becommentariëren, dus ik hoop dat iemand anders dat voor mij kan doen.)Er was een punt van zorg dat de eerste methode:

df.sample(frac=1)

een diepe kopie gemaakt of zojuist het dataframe gewijzigd. Ik heb de volgende code uitgevoerd:

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

en mijn resultaten waren:

0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70

wat betekent dat de methode niethetzelfde object retourneert, zoals werd gesuggereerd in de laatste opmerking. Deze methode maakt dus inderdaad een geschudde kopie.


Antwoord 5

Wat ook handig is, als je het voor Machine_learning gebruikt en altijd dezelfde gegevens wilt scheiden, kun je het volgende gebruiken:

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

dit zorgt ervoor dat u uw willekeurige keuze altijd reproduceerbaar houdt


Antwoord 6

Het volgende kan een van de manieren zijn:

dataframe = dataframe.sample(frac=1, random_state=42).reset_index(drop=True)

waar

frac=1betekent alle rijen van een dataframe

random_state=42betekent dat je bij elke uitvoering dezelfde volgorde aanhoudt

reset_index(drop=True)betekent het opnieuw initialiseren van de index voor gerandomiseerd dataframe


Antwoord 7

AFAIK de eenvoudigste oplossing is:

df_shuffled = df.reindex(np.random.permutation(df.index))

Antwoord 8

schud het panda’s-dataframe door een voorbeeldarray te nemen, in dit geval index, en de volgorde ervan willekeurig te maken en stel de array vervolgens in als een index van het dataframe. Sorteer nu het dataframe op index. Hier gaat je geschudde dataframe

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()

uitvoer

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

Voeg je dataframe in op de plaats van mij in bovenstaande code.


Antwoord 9

Hier is een andere manier:


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

Other episodes