2017-12-19 2 views
1

ich den Folgedatenpunkt in Panda Datenrahmen haben:Lambda-Funktion zwei Arten von Berechnungen haben

DateTime    Data 
2017-11-21 18:54:31  1 
2017-11-22 02:26:48  2 
2017-11-22 10:19:44  3 
2017-11-22 15:11:28  6 
2017-11-22 23:21:58  7 
2017-11-28 14:28:28 28 
2017-11-28 14:36:40  0 
2017-11-28 14:59:48  1 

Ich möchte eine Funktion anwenden konvertieren alle Daten größer als 1 Werte bis 1: gibt es einen Weg die folgenden zwei Lambda-Funktionen in einer (wie eine else-Anweisung) zu kombinieren?

[(lambda x: x/x)(x) for x in df['Data'] if x > 0] 
[(lambda x: x)(x) for x in df['Data'] if x <1 ] 

Endergebnis gewünscht:

df['Data'] = df['Data'].clip_upper(1) 

Oder boolean Maske ge (>=) verwenden und konvertieren zu int, wenn keine negativen Werte:

DateTime    Data 
2017-11-21 18:54:31  1 
2017-11-22 02:26:48  1 
2017-11-22 10:19:44  1 
2017-11-22 15:11:28  1 
2017-11-22 23:21:58  1 
2017-11-28 14:28:28  1 
2017-11-28 14:36:40  0 
2017-11-28 14:59:48  1 

Antwort

3

Sie clip_upper können

df['Data'] = df['Data'].ge(1).astype(int) 

print (df) 
       DateTime Data 
0 2017-11-21 18:54:31  1 
1 2017-11-22 02:26:48  1 
2 2017-11-22 10:19:44  1 
3 2017-11-22 15:11:28  1 
4 2017-11-22 23:21:58  1 
5 2017-11-28 14:28:28  1 
6 2017-11-28 14:36:40  0 
7 2017-11-28 14:59:48  1 

Aber wenn verwendet Verständnis Liste will (es sollte in größerem Datenrahmen slowier sein):

df['Data'] = [1 if x > 0 else x for x in df['Data']] 
print (df) 
       DateTime Data 
0 2017-11-21 18:54:31  1 
1 2017-11-22 02:26:48  1 
2 2017-11-22 10:19:44  1 
3 2017-11-22 15:11:28  1 
4 2017-11-22 23:21:58  1 
5 2017-11-28 14:28:28  1 
6 2017-11-28 14:36:40  0 
7 2017-11-28 14:59:48  1 

Timings:

#[8000 rows x 5 columns] 
df = pd.concat([df]*1000).reset_index(drop=True) 

In [28]: %timeit df['Data2'] = df['Data'].clip_upper(1) 
1000 loops, best of 3: 308 µs per loop 

In [29]: %timeit df['Data3'] = df['Data'].ge(1).astype(int) 
1000 loops, best of 3: 425 µs per loop 

In [30]: %timeit df['Data1'] = [1 if x > 0 else x for x in df['Data']] 
100 loops, best of 3: 3.02 ms per loop 

#[800000 rows x 5 columns] 
df = pd.concat([df]*100000).reset_index(drop=True) 

In [32]: %timeit df['Data2'] = df['Data'].clip_upper(1) 
100 loops, best of 3: 9.32 ms per loop 

In [33]: %timeit df['Data3'] = df['Data'].ge(1).astype(int) 
100 loops, best of 3: 4.76 ms per loop 

In [34]: %timeit df['Data1'] = [1 if x > 0 else x for x in df['Data']] 
1 loop, best of 3: 274 ms per loop 
4

Numpy Lösung mit np.clip -

df['Data'] = np.clip(df.Data.values, a_min=None, a_max=1) 
df 

       DateTime Data 
0 2017-11-21 18:54:31  1 
1 2017-11-22 02:26:48  1 
2 2017-11-22 10:19:44  1 
3 2017-11-22 15:11:28  1 
4 2017-11-22 23:21:58  1 
5 2017-11-28 14:28:28  1 
6 2017-11-28 14:36:40  0 
7 2017-11-28 14:59:48  1 

Pass a_min=None, um keine untere Grenze anzugeben.


Timings

df = pd.concat([df]*1000).reset_index(drop=True) 

%timeit df['Data'].clip_upper(1) 
1000 loops, best of 3: 195 µs per loop 

%timeit np.clip(df.Data.values, a_min=None, a_max=1) 
10000 loops, best of 3: 24.2 µs per loop 
+0

Dies ist eine großartige Antwort und np ist wirklich mächtig, ich werde jedoch Pick Jezrael als beste Antwort, da es datafram die interne Funktion verwendet. Ich weiß es trotzdem zu schätzen. – user97662

+0

@ user97662 kein Problem. Ich kann deine Entscheidung respektieren. Glückliche Kodierung. –

+2

@ user97662 Obwohl ich Ihre Aufmerksamkeit auf die Tatsache lenken sollte, dass meine Antwort 9 Mal besser ist als die schnellste Antwort von Jezrael. Schau dir meine Zeit an. Wenn Leistung wichtig ist, ermutige ich Sie, das zu überdenken. –

Verwandte Themen