2016-12-30 4 views
2

Ich versuche, das folgende Problem zu lösen. Es gibt einen Datenrahmen df:So extrahieren Elternknoten und nachfolgende Knoten aus Datenframe

df = 

ID GROUP_1 GROUP_2 GROUP_3 GROUP_4 
1 AAA  AAA  BBB  CCC 
2 CCC  AAA  CCC  BBB 
3 DDD  CCC  BBB  CCC 
4 ... 

Ich brauche alle Sequenzen von Gruppen zu extrahieren und sie zählen. Die Ausgabe sollte diese sein (in eckigen Klammern ich alle möglichen nachfolgenden Knoten für den gegebenen Elternknoten haben wollen):

result = 
AAA, 3, [AAA,BBB,CCC] 
BBB, 2, [CCC] 
CCC, 3, [AAA,BBB] 
DDD, 1, [CCC] 

Ich weiß, wie die Anzahl der eindeutigen Vorkommen von Gruppen zu zählen wie folgt:

df.filter(regex="^GROUP").stack().reset_index(level=1, drop=True).reset_index().drop_duplicates()[0].value_counts() 

Es gibt die Ausgabe wie diese:

AAA 2 
BBB 3 
CCC 3 
DDD 1 

aber ich weiß nicht, wie alle möglichen nachfolgenden Knoten ohne Duplikate zu extrahieren und alle Vorkommen dieser Paare zählen (einschließlich Duplikate).

+0

ich verstehe es nicht, wie Sie bekam 'DDD, 1, [CCC]' Linie? Oder 'CCC, 3, [AAA, BBB]' Linie? –

+0

@RomanPekar: Wie Sie in 'df' sehen können, hat der Wert' DDD' nur einen möglichen nachfolgenden Spaltenwert, der 'CCC' ist, und es gibt nur ein Vorkommen einer solchen Folge' ' (es kommt in Zeile 3 vor) .Dasselbe gilt für 'CCC': Dieser Wert kann zwei mögliche eindeutige Werte der folgenden Spalten haben, die 'AAA' und' BBB' sind, und insgesamt gibt es 3 Vorkommen solcher Paare: '' (Zeile 2), '' (Zeile 2), '' (Zeile 3). Ist es jetzt klarer? Vielen Dank. – Dinosaurius

Antwort

2

Eine weitere Option hier:

# melt data frame to long format 
long_df = pd.melt(df, id_vars = "ID", value_name="First") 

# create a shifted subsequent nodes column 
(long_df.assign(Second = long_df.groupby("ID").First.shift(-1)) 

# aggregation grouped by the first column 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.dropna().unique().tolist()})) 

enter image description here


variantions für mit fehlenden Werten zu tun:

Variation 1:

dropna() nach der verschobenen Spalte zu schaffen, wird dies jedes Paar fällt die nan enthält:

(long_df.assign(Second = long_df.groupby("ID").First.shift(-1)).dropna() 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.unique().tolist()})) 

Variation 2:

Tropfen fehlende Werte im Langformat-Datenrahmen vor der verschobenen Spalte zu schaffen, wird dies die nicht fehlenden Werte verbinden Recht vor Wert mit dem man nach dem fehlenden Wert fehlt:

(long_df.dropna().assign(Second = long_df.groupby("ID").First.shift(-1)) 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.unique().tolist()})) 
+0

Was ist 'First'? Entspricht es in meinem Beispiel "GROUP_"? – Dinosaurius

+0

Ich habe die Wertespalte im 'melt' in' First' umbenannt, sie entspricht den Werten unter den 'GROUP_' Spalten, aber im langen Format. – Psidom

+0

Was passiert, wenn einige Spalten 'GROUP_X' leere Werte haben? Wird diese Lösung "NaN" in die Liste in der Spalte "Second" aufnehmen? Wie man es vermeidet? Entschuldigung, ich habe diesen wichtigen Punkt in der Frage nicht erwähnt. – Dinosaurius

2

Erhalten Sie alle möglichen Werte

>>> df.set_index('ID').stack().reset_index(drop=True) 
0  AAA 
1  AAA 
2  BBB 
3  CCC 
4  CCC 
5  AAA 
6  CCC 
7  BBB 
8  DDD 
9  CCC 
10 BBB 
11 CCC 

alle nachfolgenden Werte pandas.DataFrame.shift mit Get:

>>> df3 = pd.concat([df2, df2.shift(-1)], axis=1) 
>>> df3.columns = ['k', 'v'] 
>>> df3 = df3[df3['v'].notnull()] 
>>> df3 = df3.drop_duplicates() 
>>> df3 
    k v 
0 AAA AAA 
1 AAA BBB 
2 BBB CCC 
3 CCC CCC 
4 CCC AAA 
5 AAA CCC 
6 CCC BBB 
7 BBB DDD 
8 DDD CCC 

Aggregate Werte auf Listen mit GroupBy.apply:

>>> df3.groupby('k')['v'].apply(list) 
k 
AAA [AAA, BBB, CCC] 
BBB   [CCC, DDD] 
CCC [BBB, AAA, CCC] 
DDD    [CCC] 

Oder

>>> df3.groupby('k').apply(lambda x: pd.Series([len(x), list(x['v'])])) 
    0    1 
k      
AAA 3 [AAA, BBB, CCC] 
BBB 2  [CCC, DDD] 
CCC 3 [BBB, AAA, CCC] 
DDD 1   [CCC] 
+0

Schön. Aber wie berechne ich die Anzahl aller Vorkommnisse für jeden Elternknoten, um es in das Endergebnis zu bringen? – Dinosaurius

+0

@Dinosaurus siehe aktualisiert –

+0

Danke für Ihre Lösung. Ich habe die Lösung von Psidom akzeptiert, weil sie in meinem Datensatz etwas schneller ist. – Dinosaurius

Verwandte Themen