it-swarm.com.de

Blindwerte (Leerzeichen) durch NaN in Pandas ersetzen

Ich möchte alle Werte in einem Pandas-Datenrahmen finden, die Leerzeichen enthalten (beliebige Anzahl) und diese Werte durch NaNs ersetzen.

Irgendwelche Ideen, wie man das verbessern 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 sehr gut finden:

                   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 der Mensch ist hässlich. Es ist nicht Pythonic und ich bin sicher, es ist auch nicht die effizienteste Verwendung von Pandas. Ich durchlaufe jede Spalte und führe eine boolesche Ersetzung gegen eine Spaltenmaske aus, die durch Anwenden einer Funktion erzeugt wird, die eine Regex-Suche nach jedem Wert durchführt und auf Whitespace ü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 etwas 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 den Funktionen von Pandas wie fillna() funktioniert. Der Vollständigkeit halber wäre es jedoch nett, wenn ich tatsächlich eine NaN direkt anstelle von None einfügen könnte.

93
Chris Clark

Ich denke, df.replace() macht den Job:

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'))

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

Wenn Temak darauf hinweist, verwenden Sie df.replace(r'^\s+$', np.nan, regex=True), falls Ihre gültigen Daten Leerzeichen enthalten.

114
patricksurry

Wie wäre es mit:

d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

Die Funktion applymap wendet eine Funktion auf jede Zelle des Datenrahmens an.

30
BrenBarn

Wenn Sie eine leere Zeichenfolge und Datensätze nur durch Leerzeichen ersetzen möchten, ist das richtige Antwort

df = df.replace(r'^\s*$', np.nan, regex=True)

Die akzeptierte Antwort

df.replace(r'\s+', np.nan, regex=True)

Ersetzt keine leere Zeichenfolge! Sie können sich selbst mit dem etwas aktualisierten Beispiel versuchen:

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'fo o', 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'))

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 - probieren Sie es aus.

25
Philipp Schwarz

Ich werde das tun:

df = df.apply(lambda x: x.str.strip()).replace('', np.nan)

oder

df = df.apply(lambda x: x.str.strip() if isinstance(x, str) else x).replace('', np.nan)

Sie können alle Striche entfernen und dann leere Striche durch np.nan ersetzen.

9
Xiaorong Liao

Einfachste aller Lösungen:

df = df.replace(r'^\s+$', np.nan, regex=True)
3
Gil Baggio

Wenn Sie die Daten aus der CSV-Datei exportieren, kann dies so einfach sein:

df = pd.read_csv(file_csv, na_values=' ')

Dadurch wird der Datenrahmen erstellt und leere Werte als Na ersetzt

2

Dies ist keine elegante Lösung, aber was anscheinend funktioniert, speichert XLSX und importiert es dann zurück. Die anderen Lösungen auf dieser Seite haben für mich nicht funktioniert, unsicher, warum.

data.to_Excel(filepath, index=False)
data = pd.read_Excel(filepath)
0
David Kong

sie können dazu auch einen Filter verwenden.

df = PD.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '])
    df[df=='']='nan'
    df=df.astype(float)
0
ERIC

Für eine sehr schnelle und einfache Lösung, bei der Sie die Gleichheit mit einem einzelnen Wert überprüfen, können Sie die mask-Methode verwenden.

df.mask(df == ' ')
0
Ted Petrou

Diese sind alle nah an der richtigen Antwort, aber ich würde nicht sagen, dass sie das Problem lösen und gleichzeitig für andere, die Ihren Code lesen, am besten lesbar sind. Ich würde sagen, dass die Antwort eine Kombination aus BrenBarns Antwort und tuomasttiks Kommentar unter dieser Antwort ist. Die Antwort von BrenBarn verwendet isspace builtin, unterstützt jedoch nicht das Entfernen leerer Zeichenfolgen, wie vom OP angefordert, und ich würde dies tendenziell als Standardanwendungsfall für das Ersetzen von Zeichenfolgen durch null angeben.

Ich habe es mit .apply umgeschrieben, sodass Sie es auf einem pd.Series oder pd.DataFrame aufrufen können.


Python 3:

Um leere Zeichenfolgen oder Zeichenfolgen mit Leerzeichen zu ersetzen:

df = df.apply(lambda x: np.nan if isinstance(x, str) and (x.isspace() or not x) else x)

Um Zeichenketten vollständig durch Leerzeichen zu ersetzen:

df = df.apply(lambda x: np.nan if isinstance(x, str) and x.isspace() else x)

Um dies in Python 2 zu verwenden, müssen Sie str durch basestring ersetzen.

Python 2:

Um leere Zeichenfolgen oder Zeichenfolgen mit Leerzeichen zu ersetzen:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and (x.isspace() or not x) else x)

Um Zeichenketten vollständig durch Leerzeichen zu ersetzen:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)
0
spen.smith
print(df.isnull().sum()) # check numbers of null value in each column

modifiedDf=df.fillna("NaN") # Replace empty/null values with "NaN"

# modifiedDf = fd.dropna() # Remove rows with empty values

print(modifiedDf.isnull().sum()) # check numbers of null value in each column
0
Jayantha