2016-04-05 14 views
1

sagen, dass ich ein PandasDataFrame, deren Daten aussehenVertausche Gruppen in Pandas

import numpy as np 
import pandas as pd 

n = 30 
df = pd.DataFrame({'a': np.arange(n), 
        'b': np.random.choice([0, 1, 2], n), 
        'c': np.arange(n)}) 

Frage: wie Gruppen permutieren (gruppiert nach b Spalte)?

Keine Permutation innerhalb jeder Gruppe, aber Permutation in Gruppenebene?


Beispiel

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

Nach

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

Grundsätzlich vor der Permutation, df['b'].unqiue() == [0, 1, 2], nach der Permutation, df['b'].unique() == [1, 0, 2].

+1

Was gewünschten Ausgang? – jezrael

+0

@jezrael Bitte beachten Sie die aktualisierte. – gongzhitaao

+0

Möchten Sie eine zufällige Permutation oder alle möglichen Permutationen? – ayhan

Antwort

2

Hier ist eine Antwort, die von der angenommenen Antwort auf this SO post inspiriert ist, die eine temporäre Categorical Spalte als Sortierschlüssel verwendet, um benutzerdefinierte Sortierreihenfolgen zu tun. In dieser Antwort produziere ich alle Permutationen, aber Sie können nur die erste nehmen, wenn Sie nur eine suchen.

import itertools 

df_results = list() 
orderings = itertools.permutations(df["b"].unique()) 
for ordering in orderings: 
    df_2 = df.copy() 
    df_2["b_key"] = pd.Categorical(df_2["b"], [i for i in ordering]) 
    df_2.sort_values("b_key", inplace=True) 
    df_2.drop(["b_key"], axis=1, inplace=True) 
    df_results.append(df_2) 

for df in df_results: 
    print(df) 

Die Idee dabei ist, dass wir eine neue kategoriale Variable jedes Mal, mit einer etwas anderen aufgezählten Reihenfolge, dann sortieren, indem sie es schaffen. Wir verwerfen es am Ende, wenn wir es nicht mehr brauchen.

+1

Danke! Schön. Ich warte ab, ob es andere mögliche Lösungen gibt. – gongzhitaao

+0

Danke. Ich weiß, was du meinst, ich bin daran interessiert, sie auch zu sehen. –

+1

Es scheint, dass das Hinzufügen einer Spalte notwendig ist, und Ihre Methode ist doppelt so schnell. Danke noch einmal. – gongzhitaao

1

Wenn ich Ihre Frage richtig verstanden hat, können Sie es auf diese Weise tun:

n = 30 
df = pd.DataFrame({'a': np.arange(n), 
        'b': np.random.choice([0, 1, 2], n), 
        'c': np.arange(n)}) 

order = pd.Series([1,0,2]) 

cols = df.columns 

df['idx'] = df.b.map(order) 

index = df.index 

df = df.reset_index().sort_values(['idx', 'index'])[cols] 

Schritt für Schritt:

In [103]: df['idx'] = df.b.map(order) 

In [104]: df 
Out[104]: 
    a b c idx 
0 0 2 0 2 
1 1 0 1 1 
2 2 1 2 0 
3 3 0 3 1 
4 4 1 4 0 
5 5 1 5 0 
6 6 1 6 0 
7 7 2 7 2 
8 8 0 8 1 
9 9 1 9 0 
10 10 0 10 1 
11 11 1 11 0 
12 12 0 12 1 
13 13 2 13 2 
14 14 0 14 1 
15 15 2 15 2 
16 16 1 16 0 
17 17 2 17 2 
18 18 1 18 0 
19 19 1 19 0 
20 20 0 20 1 
21 21 0 21 1 
22 22 1 22 0 
23 23 1 23 0 
24 24 2 24 2 
25 25 0 25 1 
26 26 0 26 1 
27 27 0 27 1 
28 28 1 28 0 
29 29 1 29 0 

In [105]: df.reset_index().sort_values(['idx', 'index']) 
Out[105]: 
    index a b c idx 
2  2 2 1 2 0 
4  4 4 1 4 0 
5  5 5 1 5 0 
6  6 6 1 6 0 
9  9 9 1 9 0 
11  11 11 1 11 0 
16  16 16 1 16 0 
18  18 18 1 18 0 
19  19 19 1 19 0 
22  22 22 1 22 0 
23  23 23 1 23 0 
28  28 28 1 28 0 
29  29 29 1 29 0 
1  1 1 0 1 1 
3  3 3 0 3 1 
8  8 8 0 8 1 
10  10 10 0 10 1 
12  12 12 0 12 1 
14  14 14 0 14 1 
20  20 20 0 20 1 
21  21 21 0 21 1 
25  25 25 0 25 1 
26  26 26 0 26 1 
27  27 27 0 27 1 
0  0 0 2 0 2 
7  7 7 2 7 2 
13  13 13 2 13 2 
15  15 15 2 15 2 
17  17 17 2 17 2 
24  24 24 2 24 2 
+0

Danke !! Tolle Sache. Einfach mit einfachen Profiling überprüft @ Sparc_spread Lösung scheint schneller. Aber beides funktioniert hervorragend. – gongzhitaao

Verwandte Themen