2016-06-11 5 views
1

Ich habe einen DataFrame mit Spalten A und B. Jetzt möchte ich Spalte produzieren C wie folgt aus:Forwarding Conditional Ergebnis

 A B C 
index 
1  0 50 NaN 
2  1 60 60 
3  0 40 60 
4  0 30 60 
5  1 40 40 

C den Wert von B wenn A==1 in dieser Reihe bekommt. Dann wird dieser Wert bis zum nächsten Mal in nächsten Zeilen gehalten A==1. Wie kann ich das vektorisiert machen?

Antwort

2

Sie können die Werte von B auswählen, in dem A == 1, dann nach vorne füllen:

a = pd.DataFrame({"A":[0,1,0,0,1], "B":[50,60,40,30,40]}, index=[1,2,3,4,5]) 
a["C"] = a.B[a.A == 1] 
a = a.fillna(method="ffill") 

Die ffill Verfahren pflanzt sich nach vorne die letzte gültige Beobachtung im NaNs zu füllen. Weitere Informationen finden Sie unter http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.fillna.html.

Dies gibt:

A B C 
1 0 50 NaN 
2 1 60 60 
3 0 40 60 
4 0 30 60 
5 1 40 40 
+0

ja, das ist es, dank @Seabass –

1

alternative Methode, Einzeiler, die schnellen Bit zu sein scheint:

In [301]: df['C'] = pd.Series(np.where(df.A==1, df.B, np.nan), index=df.index).ffill() 

In [302]: df 
Out[302]: 
    A B  C 
1 0 50 NaN 
2 1 60 60.0 
3 0 40 60.0 
4 0 30 60.0 
5 1 40 40.0 

Setup-500K Reihen DF:

In [310]: %paste 
def method1(a): 
    a["C"] = a.B[a.A == 1] 
    return a.fillna(method="ffill") 

def method2(df): 
    df['C'] = pd.Series(np.where(df.A==1, df.B, np.nan), index=df.index).ffill() 
    return df 
## -- End pasted text -- 

df = pd.concat([df] * 10**5, ignore_index=True) 

In [313]: df.shape 
Out[313]: (500000, 2) 

Timing:

In [311]: %timeit method1(df) 
10 loops, best of 3: 95.3 ms per loop 

In [312]: %timeit method2(df) 
100 loops, best of 3: 17.8 ms per loop 

interessant, ich dachte, dass @ Seabass Methode schneller sein sollte, aber anscheinend nicht, dass es ...

+0

definitiv die eleganteste Lösung, dank @MaxU –

+0

@Al_Iskander, Sie sind willkommen ! :) – MaxU