2017-04-19 9 views
2

Ich versuche, die .where pandas dataframe Methode zu verwenden, nur ich habe mehr als 2 Möglichkeiten (dh ich habe wenn, elif, sonst anstelle des Standardverhaltens wenn sonst)Python Pandas .where mit mehr als 2 möglichen Bedingung Eingaben

Bitte beachten Sie die folgenden Datenrahmen:

a1 = np.random.rand(7,2) 
a2 = np.random.randint(0,3,(7,1)) 
grid = np.append(a1, a2, axis=1) 
df = pd.DataFrame(grid) 

I

versucht
def test(x): 
    if x[2] == 0: 
     return 5 
    if x[2]==1: 
     return 10 
    if x[2] ==2: 
     return 50 

df.where(test) 

Aber ich Fehlermeldung "Wahrheitswert einer serie nicht eindeutig ist". Ich vermute, dies ist die richtige Richtung, aber ich bin verwirrt, wie man es erreicht. Die Dokumentation besagt, dass, wenn die Bedingung aufrufbar ist, die Eingabe als die vollständige df betrachtet wird. Aber selbst dann scheint es, dass es x[2] als die gesamte Spalte 2 betrachtet. Gibt es keine Möglichkeit, eine vektorisierte Operation für diese Aufgabe zu erreichen? Ist es nur möglich, Zeile für Zeile zu iterieren, ob mit Itrows oder Apply?

Dies ist ein Spielzeug Beispiel, um im Forum klar zu sein, ich versuche nicht, eine einfache .map in meinem wirklichen Leben Problem zu tun. Bitte halten Sie die "Test" -Funktion als eine separate Funktion, die übergeben werden muss, wenn Sie antworten, da dies meine Schwierigkeit ist.

Antwort

2
np.random.seed(100) 
a1 = np.random.rand(7,2) 
a2 = np.random.randint(0,3,(7,1)) 
grid = np.append(a1, a2, axis=1) 
df = pd.DataFrame(grid) 
print (df) 
      0   1 2 
0 0.543405 0.278369 2.0 
1 0.424518 0.844776 2.0 
2 0.004719 0.121569 0.0 
3 0.670749 0.825853 0.0 
4 0.136707 0.575093 1.0 
5 0.891322 0.209202 1.0 
6 0.185328 0.108377 1.0 

Lösung mit map:

d = {0:5,1:10,2:50} 
df['d'] = df[2].map(d) 
print (df) 
      0   1 2 d 
0 0.543405 0.278369 2.0 50 
1 0.424518 0.844776 2.0 50 
2 0.004719 0.121569 0.0 5 
3 0.670749 0.825853 0.0 5 
4 0.136707 0.575093 1.0 10 
5 0.891322 0.209202 1.0 10 
6 0.185328 0.108377 1.0 10 

Eine andere Lösung mit numpy.where:

df['d'] = np.where(df[2] == 0, 5, 
      np.where(df[2]== 1, 10, 50)) 

print (df) 
      0   1 2 d 
0 0.543405 0.278369 2.0 50 
1 0.424518 0.844776 2.0 50 
2 0.004719 0.121569 0.0 5 
3 0.670749 0.825853 0.0 5 
4 0.136707 0.575093 1.0 10 
5 0.891322 0.209202 1.0 10 
6 0.185328 0.108377 1.0 10 

EDIT:

Für separate Funktion besteht die Möglichkeit, apply mit dem Parameter axis=1 zur Verarbeitung df von rows:

def test(x): 
    #print (x) 
    if x[2] == 0: 
     return 5 
    if x[2]==1: 
     return 10 
    if x[2] ==2: 
     return 50 

df['d'] = df.apply(test, axis=1) 
print (df) 
      0   1 2 d 
0 0.543405 0.278369 2.0 50 
1 0.424518 0.844776 2.0 50 
2 0.004719 0.121569 0.0 5 
3 0.670749 0.825853 0.0 5 
4 0.136707 0.575093 1.0 10 
5 0.891322 0.209202 1.0 10 
6 0.185328 0.108377 1.0 10 

Aber wenn Bedarf Funktion:

def test(x): 
    return np.where(x == 0, 5, np.where(x== 1, 10, 50)) 

print (test(df[2])) 
[50 50 5 5 10 10 10] 
+0

HALLO, danke. Können Sie eine Antwort zeigen, indem Sie die Funktion "test" als separate Funktion behalten, die entweder in der Karte oder wo übergeben wird? Dies wird mir in meinem realen Beispiel helfen. –

+0

Ok thx: also ich verstehe, ich muss entweder anwenden oder Iterrows hier - gibt es keine Möglichkeit, das Ergebnis mit einer vektorisierten Operation zu erreichen, wie ich dachte, wäre möglich? Im Dokument der Wo-Methode erwähnen sie die Möglichkeit, eine Callable zu verwenden, was ich hier versuche zu tun: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.where. html –

+0

ja ich denke, dass sollte es tun. Ich werde es mal testen aber ich vermute wo schneller ist als bewerben? In diesem Fall suche ich genau nach –

Verwandte Themen