2016-04-03 10 views
1

Ich verwende Python 2.7 (in ipython Notebook) und ich habe folgendes Pandas Datenrahmen:Python: Wie finden Modus (1 col - Objekt), durch 2. Spalte gruppiert, Ausgabe in der 3. Spalte

df = pd.DataFrame({'Client': [161252, 8858, 8858, 8858, 8858, 56552, 56552], 
       'State': ['NE', 'MN', 'MN', 'TX', 'MN', 'NJ', 'WA']}) 

Was ich tun möchte, ist, die Zeilen nach "Client" zu gruppieren, den Modus "Status" für jeden Client zu finden und dann die Ausgabe in eine neue Spalte namens "Mode_State" zu setzen. Die Spalte "State" ist ein Python-Objekt.

Ich habe das versucht, folgende:

from scipy.stats import mode 
df.insert(1, 'Mode_State', ' ') 

df['Mode_State'] = df['State'].groupby(df["Client"]).transform(mode) 
df 

Daraus ergibt sich wie folgt zusammen:

Client Mode_State State 
0 161252 NE   NE 
1 8858 MN   MN 
2 8858 3   MN 
3 8858 MN   TX 
4 8858 3   MN 
5 56552 [NJ]   NJ 
6 56552 [1]   WA 

Ich weiß, dass scipy.stats auch die Nummer des Modus enthält, so habe ich versucht, die folgende (nur um die zwei Zeichen State Information, nicht die Mode-Nummer):

df['Mode_State'] = df['State'].groupby(df["Client"]).transform(mode[0]) 
df 

Was natürlich gab mir:

TypeError         Traceback (most recent call last) 
<ipython-input-42-1050c2b46d90> in <module>() 
     1 from scipy.stats import mode 
     2 
----> 3 df['Mode_State'] =  df['State'].groupby(df["Client"]).transform(mode[0]) 
     4 df 

TypeError: 'function' object has no attribute '__getitem__' 

ich auch die verschiedenen Antworten auf Stack versucht haben, die mit Strings umgehen (z Lambda, Agg, Karte usw.). und bekomme Variationen von meinem ersten Ergebnis oder Fehlermeldungen. Wenn es zwei gleiche Modi gibt (z. B. Client 56552 hat NJ & WA), ist es in Ordnung, dass das Ergebnis als das niedrigste zurückgegeben wird.

Ich wäre dankbar, wenn jemand ein paar Tipps hat, um mich in die richtige Richtung zu weisen.

Danke (Anmerkung, bin offensichtlich immer noch lernen Python, also bin nicht sehr erfahren. Haben meinen Weg durch Wes McKinney Python für Datenanalyse gearbeitet, aber das Arbeiten mit Strings erweist sich ein bisschen schwieriger für mich).

Antwort

1
df['Mode_State'] = df.groupby('Client').State.transform(lambda group: group.mode()) 


>>> df 
    Client State Mode_State 
0 161252 NE   NE 
1 8858 MN   MN 
2 8858 MN   MN 
3 8858 TX   MN 
4 8858 MN   MN 
5 56552 NJ   NJ 
6 56552 WA   WA 
+0

Danke Alexander, das hat gut für mich funktioniert. Nur eine Frage, Client 56552 hat gleiche Modi (NJ & WA), also gibt es eine Möglichkeit, die Antwort als die niedrigste (d. H. NJ & NJ) zu füllen? – gincard

+1

Nach der Doc-Zeichenfolge für df.mode: 'Ruft die Modi jedes Elements entlang der ausgewählten Achse ab. Leer, wenn nichts 2+ Vorkommen hat. Fügt eine Zeile für jeden Modus pro Etikett hinzu, füllt die Lücken mit nan. Beachten Sie, dass für die ausgewählte Achse mehrere Werte zurückgegeben werden können (wenn mehr als ein Element die maximale Häufigkeit gemeinsam hat), was der Grund ist, warum ein Datenframe zurückgegeben wird. Wenn Sie fehlende Werte mit dem Modus in einem Datenrahmen '' df' 'imputieren möchten, können Sie das tun: '' df.fillna (df.mode(). Iloc [0]) '' ' – Alexander

0
df['Mode_State'] =df['State'].groupby(df["Client"]).transform(lambda x: x.value_counts().index[0]) 
+0

Dank für die Reaktion - das ist die Zählungen für mich zurück (das heißt als eine Zahl, so hat 8858 4 als eine Reaktion in jeder Reihe von Mode_State), nicht der gebräuchlichste Zustand (z.B. MN). – gincard

+0

das funktioniert. Allerdings verwendet Alexanders Vorschlag die eingebaute Funktion (wahrscheinlich schneller). Meine Lösung kann in manchen Fällen flexibler sein. Insbesondere denke ich, dass Wert zählt, um gebundene Werte nach lexikographischer Ordnung zu sortieren, also gibt es eine gewisse Vorhersagbarkeit, in Bezug auf die man zuerst kommt. –

+0

Vielen Dank dafür, ich werde dies für zukünftige Verwendung beachten und Ihre Klarstellung zu schätzen wissen. – gincard

Verwandte Themen