2014-02-06 11 views
36

Ich mache wahrscheinlich etwas sehr dumm, aber ich bin ratlos.Conditional Replace Pandas

Ich habe einen Datenrahmen und ich möchte die Werte in einer bestimmten Spalte ersetzen, die einen Wert mit Null überschreiten. Ich hatte gedacht, das war ein Weg, dies zu erreichen:

df[df.my_channel > 20000].my_channel = 0 

Wenn ich den Kanal in einen neuen Datenrahmen kopiere einfach:

df2 = df.my_channel 

df2[df2 > 20000] = 0 

dies tut genau das, was ich will, aber scheint nicht zu funktionieren mit dem Kanal als Teil des ursprünglichen Datenrahmens.

Danke ist Fortschritt.

Ben

+0

gefunden, was ich glaube, Sie waren auf der Suche nach [hier] (http://stackoverflow.com/q/37841525/2662901). – feetwet

Antwort

49

.ix Indexer für Pandas Version vor 0.20.0 in Ordnung funktioniert, aber seit 0.20.0 Pandas, die .ix Indexer ist deprecated, so sollten Sie vermeiden, es zu benutzen. Stattdessen können Sie .loc oder iloc Indexer verwenden. Sie können dieses Problem lösen, indem sie:

mask = df.my_channel > 20000 
column_name = 'my_channel' 
df.loc[mask, column_name] = 0 

mask hilft Ihnen, die Zeilen aus, in dem df.my_channel > 20000True, während df.loc[mask, column_name] = 0 den Wert 0 zu den ausgewählten Zeilen setzt, wo mask in der Spalte enthält die Namen column_name ist.

Update: In diesem Fall sollten Sie loc verwenden, denn wenn Sie iloc verwenden, erhalten Sie eine NotImplementedError bekommen sage Ihnen, dass iLocation basierend boolean Indizierung auf einem Integer-Typ nicht verfügbar ist.

+7

lmiguelvargasfs Antwort sollte als die richtige getaggt werden, angesichts der letzten Änderungen an Pandas – ramhiser

+1

Kannst du 'iloc benutzen? 'Mit dieser Art von Maske? Es scheint nicht für mich zu funktionieren (obwohl "loc" gut funktioniert).Wenn "iloc" in diesem Fall nicht funktioniert, sollte vielleicht klargestellt werden, dass "loc" 'ix' ersetzen sollte, um dieses Problem zu lösen, und in anderen Situationen durch" iloc "ersetzt werden kann? – LangeHaare

+2

@LangeHaare, ich habe gerade versucht, was du gesagt hast, und du hast recht, es funktioniert nicht für 'iloc'. Ich werde meine Antwort aktualisieren, um dieses Problem zu beheben. Vielen Dank, dass Sie mich wissen lassen. – lmiguelvargasf

56

Versuchen

df.ix[df.my_channel > 20000, 'my_channel'] = 0 
+6

Danke. Ich habe auch meine eigene Lösung gefunden, nämlich: df.my_channel [df.my_channel> 20000] = 0 – BMichell

+1

@BMichell Ich denke, Ihre Lösung könnte Ihnen Warnungen in 0.13 geben, hatte noch keine Chance, es auszuprobieren – lowtech

+0

Ertragsfehler: /opt/anaconda3/envs/python35/lib/python3.5/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: Es wird versucht, einen Wert für eine Kopie eines Slices von einem DataFrame festzulegen Siehe die Vorbehalte in Die Dokumentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy "" "Einstiegspunkt zum Starten eines IPython-Kernel. –

0

Ich persönlich mag die np.where-Funktion, die wie folgt funktioniert:

df['X'] = np.where(df['Y']>=50, 'yes', 'no') 

In Ihrem Fall würden Sie wollen:

import numpy as np df.['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)

+0

Ich mag np.where too nur "." muss aus der Anweisung entfernt werden. so sollte es sein. df ['mein_kanal'] = np.where (df.mein_kanal> 20000, 0, df.mein_kanal) –