Ersetzen von Leerwerten (Leerraum) durch NaN in Pandas
Lesezeit: 6 Minuten
Chris Clark
Ich möchte alle Werte in einem Pandas-Datenrahmen finden, die Leerzeichen (beliebige Menge) enthalten, und diese Werte durch NaNs ersetzen.
Irgendwelche Ideen, wie dies verbessert werden kann?
Grundsätzlich möchte ich das drehen:
A B C
2000-01-01 -0.532681 foo 0
2000-01-02 1.490752 bar 1
2000-01-03 -1.387326 foo 2
2000-01-04 0.814772 baz
2000-01-05 -0.222552 4
2000-01-06 -1.176781 qux
Das mögen:
A B C
2000-01-01 -0.532681 foo 0
2000-01-02 1.490752 bar 1
2000-01-03 -1.387326 foo 2
2000-01-04 0.814772 baz NaN
2000-01-05 -0.222552 NaN 4
2000-01-06 -1.176781 qux NaN
Ich habe es mit dem folgenden Code geschafft, aber Mann ist es hässlich. Es ist nicht pythonisch und ich bin mir sicher, dass es auch nicht die effizienteste Verwendung von Pandas ist. Ich durchlaufe jede Spalte und führe eine boolesche Ersetzung gegen eine Spaltenmaske durch, die durch Anwenden einer Funktion generiert wird, die eine Regex-Suche nach jedem Wert durchführt und mit Leerzeichen übereinstimmt.
for i in df.columns:
df[i][df[i].apply(lambda i: True if re.search('^s*$', str(i)) else False)]=None
Es könnte ein wenig optimiert werden, indem nur Felder durchlaufen werden, die leere Zeichenfolgen enthalten könnten:
if df[i].dtype == np.dtype('object')
Aber das ist keine große Verbesserung
Und schließlich setzt dieser Code die Zielzeichenfolgen auf None, was mit Pandas-Funktionen wie funktioniert fillna()aber es wäre der Vollständigkeit halber schön, wenn ich tatsächlich eine einfügen könnte NaN direkt statt None.
Was Sie wirklich wollen, ist in der Lage zu sein, zu verwenden replace mit einem Regex … (vielleicht sollte dies als Feature angefordert werden).
Für diejenigen, die genau ein einzelnes Leerzeichen als fehlend umwandeln möchten, sehen Sie sich diese einfache Lösung unten an
– Ted Petrou
3. November 17 um 22:50 Uhr
patricksurry
Ich denke df.replace() macht den Job, da Pandas 0.13:
df = pd.DataFrame([
[-0.532681, 'foo', 0],
[1.490752, 'bar', 1],
[-1.387326, 'foo', 2],
[0.814772, 'baz', ' '],
[-0.222552, ' ', 4],
[-1.176781, 'qux', ' '],
], columns="A B C".split(), index=pd.date_range('2000-01-01','2000-01-06'))
# replace field that's entirely space (or empty) with NaN
print(df.replace(r'^s*$', np.nan, regex=True))
Produziert:
A B C
2000-01-01 -0.532681 foo 0
2000-01-02 1.490752 bar 1
2000-01-03 -1.387326 foo 2
2000-01-04 0.814772 baz NaN
2000-01-05 -0.222552 NaN 4
2000-01-06 -1.176781 qux NaN
Wie Temak darauf hingewiesen hat, verwenden df.replace(r'^s+$', np.nan, regex=True) falls Ihre gültigen Daten Leerzeichen enthalten.
Regex ist ein boolesches Flag. Vielleicht meinst du pd.Series(["1", "#", "9", " .", None]).replace(r"( +.)|#", "X", regex=True).values was gibt ['1', 'X', '9', 'X', None]
– Patricksurry
3. November 15 um 16:27 Uhr
2 Jahre später habe ich die akzeptierte Antwort darauf geändert, jetzt, wo Pandas dies unterstützen. Danke!
– Chris Clark
4. November 15 um 19:50 Uhr
HINWEIS: Wenn Sie nicht möchten, dass ein Element mit Leerzeichen in der Mitte durch NaN ersetzt wird, verwenden Sie es df.replace(r'^s+$', np.nan, regex=True)
– Temak
1. August 16 um 10:13 Uhr
Ich habe versucht, dies zu verwenden, fand aber heraus, dass r’^s*$’ der zu verwendende Ausdruck sein sollte. ohne ^ und $ wird jede Zeichenfolge mit zwei aufeinanderfolgenden Leerzeichen gefunden. Außerdem wurde + in * geändert, um die leere Zeichenfolge “” in die Liste der Dinge aufzunehmen, die in NaN konvertiert werden sollen
– Meisterjoghurt
18. November 16 um 17:36 Uhr
Ich versuche Ihre Lösung in meinem Code, aber es hat keine Wirkung. Ich versuche “Energie[“Energy Supply”].replace(to_replace = “…”, value = np.NaN)”. Ich möchte die Zeichenfolge “…” in NaN-Werte ändern, aber es tut nichts und gibt denselben Datenrahmen zurück.
– NeugierigerLerner
7. Januar 18 um 10:41 Uhr
Philipp Schwarz
Wenn Sie eine leere Zeichenfolge und Datensätze nur durch Leerzeichen ersetzen möchten, wird die richtige Antwort ist!:
df = df.replace(r'^s*$', np.nan, regex=True)
Die akzeptierte Antwort
df.replace(r's+', np.nan, regex=True)
Ersetzt keinen leeren String!, können Sie es mit dem gegebenen Beispiel leicht aktualisiert selbst versuchen:
Beachten Sie auch, dass ‘fo o’ nicht durch Nan ersetzt wird, obwohl es ein Leerzeichen enthält. Beachten Sie außerdem, dass ein einfaches:
df.replace(r'', np.NaN)
Funktioniert auch nicht – ausprobieren.
BrenBarn
Wie wäre es mit:
d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)
Der applymap function wendet eine Funktion auf jede Zelle des Datenrahmens an.
Was für eine schöne Verbesserung! Ich hätte im Nachhinein daran denken sollen, habe mich aber aus irgendeinem Grund daran gehindert, boolesche Ersetzungen vorzunehmen. Eine Frage: Gibt es einen Vorteil bei der Überprüfung der Basiszeichenfolge gegenüber nur str(x).isspace()?
– Chris Clark
18. November 12 um 23:50 Uhr
@ChrisClark: Beides ist in Ordnung, obwohl ich vermuten würde, dass das isinstance wird etwas schneller.
– BrenBarn
18. November 12 um 23:55 Uhr
Der Verweis auf “basestring” im obigen Code funktioniert nicht in Python 3…. in diesem Fall versuchen Sie es stattdessen mit “str”.
– Spike-Williams
9. Februar 15 um 20:39 Uhr
Beachten Sie, dass diese Lösung keine leeren Zeichenfolgen ersetzt ''. Um auch leere Strings zu berücksichtigen, verwenden Sie: d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and (not x or x.isspace()) else x)
– tuomastik
31. Mai ’17 um 12:34 Uhr
In Python 3.x das korrekte Äquivalent für isinstance(x, basestring) ist isinstance(x, str)
Sie können alle str entfernen und dann leere str durch ersetzen np.nan.
Ibrahim Rupawala
Wenn Sie die Daten aus der CSV-Datei exportieren, kann es so einfach sein:
df = pd.read_csv(file_csv, na_values=" ")
Dadurch wird der Datenrahmen erstellt und leere Werte als Na ersetzt
Eine weitere Option … mit skipinitialspace=True Entfernt auch alle Leerzeichen nach dem Trennzeichen, die dazu führen würden, dass jede Länge von Leerzeichen, leere Zeichenfolgen als gelesen werden nan. Wenn Sie jedoch aus irgendeinem Grund die anfänglichen Leerzeichen beibehalten möchten, ist diese Option keine gute Wahl.
– Rajshekar Reddy
31. Oktober 18 um 3:31 Uhr
Gil Baggio
Einfachste aller Lösungen:
df = df.replace(r'^s+$', np.nan, regex=True)
Eine weitere Option … mit skipinitialspace=True Entfernt auch alle Leerzeichen nach dem Trennzeichen, die dazu führen würden, dass jede Länge von Leerzeichen, leere Zeichenfolgen als gelesen werden nan. Wenn Sie jedoch aus irgendeinem Grund die anfänglichen Leerzeichen beibehalten möchten, ist diese Option keine gute Wahl.
– Rajshekar Reddy
31. Oktober 18 um 3:31 Uhr
Ted Petrou
Für eine sehr schnelle und einfache Lösung, bei der Sie die Gleichheit mit einem einzelnen Wert prüfen, können Sie die verwenden mask Methode.
df.mask(df == ' ')
.
7590200cookie-checkErsetzen von Leerwerten (Leerraum) durch NaN in Pandasyes
Was Sie wirklich wollen, ist in der Lage zu sein, zu verwenden
replace
mit einem Regex … (vielleicht sollte dies als Feature angefordert werden).– Andy Hayden
18. November 12 um 23:23 Uhr
Ich habe ein Github-Problem für diese Funktion erstellt: github.com/pydata/pandas/issues/2285 . Wäre dankbar für PRs! 🙂
– Chang She
19. November 12 um 0:00 Uhr
Für diejenigen, die genau ein einzelnes Leerzeichen als fehlend umwandeln möchten, sehen Sie sich diese einfache Lösung unten an
– Ted Petrou
3. November 17 um 22:50 Uhr