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?

zegkljan
quelle

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)
Alex Riley
quelle
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
ErnestScribbler
quelle
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.

Ffisegydd
quelle
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
jjs
quelle
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

ffill hat jetzt seine eigene Methode pd.DataFrame.ffill

df.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
piRSquared
quelle
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)
DeveScie
quelle
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
Suvo
quelle
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
Hodza
quelle
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

Md Jewele Islam
quelle