Wie ersetze ich NaNs durch vorhergehende Werte in pandas DataFrame?


140

Angenommen, ich habe einen DataFrame mit einigen NaNs:

>>> import pandas as pd
>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df
    0   1   2
0   1   2   3
1   4 NaN NaN
2 NaN NaN   9

Was ich tun muss, ist, jeden NaNdurch den ersten Nichtwert NaNin derselben Spalte darüber zu ersetzen . Es wird angenommen, dass die erste Zeile niemals ein enthält NaN. Für das vorherige Beispiel wäre das Ergebnis also

   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

Ich kann einfach den gesamten DataFrame Spalte für Spalte, Element für Element durchlaufen und die Werte direkt festlegen. Gibt es jedoch eine einfache (optimalerweise schleifenfreie) Möglichkeit, dies zu erreichen?

Antworten:


213

Sie können die fillnaMethode im DataFrame verwenden und die Methode als ffill(Forward Fill) angeben :

>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df.fillna(method='ffill')
   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

Diese Methode...

Propagieren Sie die letzte gültige Beobachtung vorwärts zur nächsten gültigen

Um den umgekehrten Weg zu gehen, gibt es auch eine bfillMethode.

Diese Methode ändert den vorhandenen DataFrame nicht. Sie müssen den zurückgegebenen DataFrame erneut an eine Variable binden oder Folgendes angeben inplace=True:

df.fillna(method='ffill', inplace=True)

31

Die akzeptierte Antwort ist perfekt. Ich hatte eine verwandte, aber etwas andere Situation, in der ich vorwärts gehen musste, aber nur innerhalb von Gruppen. Wenn jemand das gleiche Bedürfnis hat, wissen Sie, dass fillna für ein DataFrameGroupBy-Objekt funktioniert.

>>> example = pd.DataFrame({'number':[0,1,2,nan,4,nan,6,7,8,9],'name':list('aaabbbcccc')})
>>> example
  name  number
0    a     0.0
1    a     1.0
2    a     2.0
3    b     NaN
4    b     4.0
5    b     NaN
6    c     6.0
7    c     7.0
8    c     8.0
9    c     9.0
>>> example.groupby('name')['number'].fillna(method='ffill') # fill in row 5 but not row 3
0    0.0
1    1.0
2    2.0
3    NaN
4    4.0
5    4.0
6    6.0
7    7.0
8    8.0
9    9.0
Name: number, dtype: float64

genau das, wonach ich gesucht habe, ty
Tony

18

Sie können pandas.DataFrame.fillnamit der method='ffill'Option verwenden. 'ffill'steht für 'Forward Fill' und verbreitet die letzte gültige Beobachtung vorwärts. Die Alternative ist, 'bfill'dass es genauso funktioniert, aber rückwärts.

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
df = df.fillna(method='ffill')

print(df)
#   0  1  2
#0  1  2  3
#1  4  2  3
#2  4  2  9

Es gibt auch eine direkte Synonymfunktion dafür pandas.DataFrame.ffill, um die Dinge einfacher zu machen.


13

Eine Sache, die mir beim Ausprobieren dieser Lösung aufgefallen ist, ist, dass ffill und bfill nicht ganz funktionieren, wenn Sie am Anfang oder am Ende des Arrays N / A haben. Du brauchst beides.

In [224]: df = pd.DataFrame([None, 1, 2, 3, None, 4, 5, 6, None])

In [225]: df.ffill()
Out[225]:
     0
0  NaN
1  1.0
...
7  6.0
8  6.0

In [226]: df.bfill()
Out[226]:
     0
0  1.0
1  1.0
...
7  6.0
8  NaN

In [227]: df.bfill().ffill()
Out[227]:
     0
0  1.0
1  1.0
...
7  6.0
8  6.0

Brillant. Ich brauchte genau das für mein Problem. Vorher und nachher füllen. Vielen Dank.
Prometheus

Toll. Ich brauche diese Lösung. Vielen Dank
Junkrat


5

Nur eine Spaltenversion

  • Füllen Sie NAN mit dem letzten gültigen Wert
df[column_name].fillna(method='ffill', inplace=True)
  • Füllen Sie NAN mit dem nächsten gültigen Wert
df[column_name].fillna(method='backfill', inplace=True)

5

Ich stimme nur der ffillMethode zu, aber eine zusätzliche Information ist, dass Sie die Vorwärtsfüllung mit dem Schlüsselwortargument begrenzen können limit.

>>> import pandas as pd    
>>> df = pd.DataFrame([[1, 2, 3], [None, None, 6], [None, None, 9]])

>>> df
     0    1   2
0  1.0  2.0   3
1  NaN  NaN   6
2  NaN  NaN   9

>>> df[1].fillna(method='ffill', inplace=True)
>>> df
     0    1    2
0  1.0  2.0    3
1  NaN  2.0    6
2  NaN  2.0    9

Jetzt mit limitSchlüsselwortargument

>>> df[0].fillna(method='ffill', limit=1, inplace=True)

>>> df
     0    1  2
0  1.0  2.0  3
1  1.0  2.0  6
2  NaN  2.0  9

1

In meinem Fall haben wir Zeitreihen von verschiedenen Geräten, aber einige Geräte konnten während eines bestimmten Zeitraums keinen Wert senden. Wir sollten also NA-Werte für jedes Gerät und jeden Zeitraum erstellen und danach Fillna ausführen.

df = pd.DataFrame([["device1", 1, 'first val of device1'], ["device2", 2, 'first val of device2'], ["device3", 3, 'first val of device3']])
df.pivot(index=1, columns=0, values=2).fillna(method='ffill').unstack().reset_index(name='value')

Ergebnis:

        0   1   value
0   device1     1   first val of device1
1   device1     2   first val of device1
2   device1     3   first val of device1
3   device2     1   None
4   device2     2   first val of device2
5   device2     3   first val of device2
6   device3     1   None
7   device3     2   None
8   device3     3   first val of device3

0

Sie können fillnaNaN-Werte entfernen oder ersetzen.

NaN entfernen

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])

df.fillna(method='ffill')
     0    1    2
0  1.0  2.0  3.0
1  4.0  2.0  3.0
2  4.0  2.0  9.0

NaN ersetzen

df.fillna(0) # 0 means What Value you want to replace 
     0    1    2
0  1.0  2.0  3.0
1  4.0  0.0  0.0
2  0.0  0.0  9.0

Referenz pandas.DataFrame.fillna

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.