Skip to content

pandas: Interpolieren von NaN mit interpolate()

Python

Sie können fehlende Werte (NaN) in pandas.DataFrame und Series mit interpolate() interpolieren.

Dieser Artikel hat folgenden Inhalt.

  • Grundlegende Verwendung von interpolate()
    • Zeile oder Spalte:axis
    • Maximale Anzahl auf gleichzeitiger zu füllender NaNs:limit
    • Richtung zu interpolieren:limit_direction
    • Interpolieren oder extrapolieren oder beides:limit_area
    • An Ort und Stelle operieren:inplace
  • Interpolationsmethode:method
    • Lineare Interpolation:linear, index, values
    • Vorhandene Werte verwenden:ffill, pad, bfill, backfill
    • Spline-Interpolation:spline
    • Andere
  • Für Zeitreihendaten
  • Falls der Datentyp dtype Objekt ist (z. B. String)

Verwenden Sie dropna() und fillna(), um fehlende Werte NaN zu entfernen oder sie mit einem bestimmten Wert zu füllen. Siehe die folgenden Artikel.

Grundlegende Verwendung von interpolate()

Der folgende pandas.DataFrame wird als Beispiel verwendet.

import pandas as pd
import numpy as np

df = pd.DataFrame({'col1': [0, np.nan, np.nan, 3, 4],
                   'col2': [np.nan, 1, 2, np.nan, np.nan],
                   'col3': [4, np.nan, np.nan, 7, 10]})
print(df)
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   NaN   1.0   NaN
# 2   NaN   2.0   NaN
# 3   3.0   NaN   7.0
# 4   4.0   NaN  10.0

Standardmäßig wird für jede Spalte eine lineare Interpolation durchgeführt. Derselbe Wert wird für Nan unten wiederholt, und Nan oben bleibt unverändert.

print(df.interpolate())
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   1.0   1.0   5.0
# 2   2.0   2.0   6.0
# 3   3.0   2.0   7.0
# 4   4.0   2.0  10.0

Zeile oder Spalte:axis

Wenn Achse = 1, wird für jede Zeile interpoliert. Derselbe Wert wird für das NaN ganz rechts wiederholt, und das NaN ganz links bleibt unverändert.

print(df.interpolate(axis=1))
#    col1  col2  col3
# 0   0.0   2.0   4.0
# 1   NaN   1.0   1.0
# 2   NaN   2.0   2.0
# 3   3.0   5.0   7.0
# 4   4.0   7.0  10.0

Maximale Anzahl auf gleichzeitiger zu füllender NaNs:limit

Wenn NaNs auf der Vorderseite dargestellt sind, können Sie mit dem Argument limit sterben maximale Anzahl der Interpolationen angeben. Der Standardwert ist None, was bedeutet, dass alle auf betrachteten NaNs interpoliert werden.

print(df.interpolate(limit=1))
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   1.0   1.0   5.0
# 2   NaN   2.0   NaN
# 3   3.0   2.0   7.0
# 4   4.0   NaN  10.0

Richtung zu interpolieren:limit_direction

Die zu interpolierende Richtung wird mit dem Argument limit_direction als „forward“, „backward“ oder „both“ angegeben.

print(df.interpolate(limit=1, limit_direction='forward'))
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   1.0   1.0   5.0
# 2   NaN   2.0   NaN
# 3   3.0   2.0   7.0
# 4   4.0   NaN  10.0

print(df.interpolate(limit=1, limit_direction='backward'))
#    col1  col2  col3
# 0   0.0   1.0   4.0
# 1   NaN   1.0   NaN
# 2   2.0   2.0   6.0
# 3   3.0   NaN   7.0
# 4   4.0   NaN  10.0

print(df.interpolate(limit=1, limit_direction='both'))
#    col1  col2  col3
# 0   0.0   1.0   4.0
# 1   1.0   1.0   5.0
# 2   2.0   2.0   6.0
# 3   3.0   2.0   7.0
# 4   4.0   NaN  10.0

Wie oben erwähnt, bleiben NaNs oben (oder links) standardmäßig, aber standardmäßig, wenn Sie limit_direction=’both‘ setzen, werden beide Enden interpoliert.

print(df.interpolate(limit_direction='both'))
#    col1  col2  col3
# 0   0.0   1.0   4.0
# 1   1.0   1.0   5.0
# 2   2.0   2.0   6.0
# 3   3.0   2.0   7.0
# 4   4.0   2.0  10.0

Mit dem Argument limit_area can SIE den zu interpolierenden Bereich angeben.

  • ‚innen‘: Nur Interpolation
  • ‚außerhalb‘: Nur Hochrechnung
  • Keine (Standard): Sowohl Interpolation als auch Extrapolation
print(df.interpolate(limit_area='inside'))
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   1.0   1.0   5.0
# 2   2.0   2.0   6.0
# 3   3.0   NaN   7.0
# 4   4.0   NaN  10.0

print(df.interpolate(limit_area='outside'))
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   NaN   1.0   NaN
# 2   NaN   2.0   NaN
# 3   3.0   2.0   7.0
# 4   4.0   2.0  10.0

print(df.interpolate(limit_area='outside', limit_direction='both'))
#    col1  col2  col3
# 0   0.0   1.0   4.0
# 1   NaN   1.0   NaN
# 2   NaN   2.0   NaN
# 3   3.0   2.0   7.0
# 4   4.0   2.0  10.0

Beachten Sie, dass das Wort „Extrapolation“ der Einfachheit halber verwendet WIRD, aber wie SIE den vorstehenden Ergebnisse entnehmen können, Sind bei der linearen Interpolation (Standard) die Werte Wiederholungen der Endwerte und Werden nicht linear extrapoliert. Bei der unten beschriebenen Spline-Interpolation werden die äußeren Werte extrapoliert und nicht wiederholt.

An Ort und Stelle operieren:inplace

Wie bei vielen anderen Methoden can SIE das Objekt selbst mit inplace=True aktualisieren.

df.interpolate(inplace=True)
print(df)
#    col1  col2  col3
# 0   0.0   NaN   4.0
# 1   1.0   1.0   5.0
# 2   2.0   2.0   6.0
# 3   3.0   2.0   7.0
# 4   4.0   2.0  10.0

Interpolationsmethode:method

Die Interpolationsmethode wird durch die erste Argumentmethode angegeben. Der Standardwert ist ‚linear‘ (lineare Interpolation).

Lineare Interpolation:linear, index, values

Bei method=’linear‘ (Standard) wird der Index ignoriert, aber bei method=’index‘ oder method=’values‘ wird mit dem Indexwert interpoliert.

s = pd.Series([0, np.nan, np.nan, 3],
              index=[0, 4, 6, 8])
print(s)
# 0    0.0
# 4    NaN
# 6    NaN
# 8    3.0
# dtype: float64

print(s.interpolate())
# 0    0.0
# 4    1.0
# 6    2.0
# 8    3.0
# dtype: float64

print(s.interpolate('index'))
# 0    0.00
# 4    1.50
# 6    2.25
# 8    3.00
# dtype: float64

If es Sich bei der Indexspalte um Buchstaben handelt, ist method=’linear‘ (Standard) in Ordnung, aber wenn method=’index‘ oder method=’values‘, wird ein Fehler ausgelöst.

s.index = list('abcd')
print(s)
# a    0.0
# b    NaN
# c    NaN
# d    3.0
# dtype: float64

print(s.interpolate())
# a    0.0
# b    1.0
# c    2.0
# d    3.0
# dtype: float64

# print(s.interpolate('index'))
# TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

Vorhandene Werte verwenden:ffill, pad, bfill, backfill

NaNs werden mit dem bereits vorhandenen Wert gefüllt, wenn method=’ffill‘ oder method=’pad‘, oder mit dem nächsten vorhandenen Wert, wenn method=’bfill‘ oder method=’backfill‘.

s = pd.Series([np.nan, 1, np.nan, 2, np.nan])
print(s)
# 0    NaN
# 1    1.0
# 2    NaN
# 3    2.0
# 4    NaN
# dtype: float64

print(s.interpolate('ffill'))
# 0    NaN
# 1    1.0
# 2    1.0
# 3    2.0
# 4    2.0
# dtype: float64

print(s.interpolate('bfill'))
# 0    1.0
# 1    1.0
# 2    2.0
# 3    2.0
# 4    NaN
# dtype: float64

Es sollte limit_direction=’forward‘ sein, wenn method=“ffill‘, ‚pad‘, und limit_direction=’backward‘ wenn method=“bfill‘, ‚backfill‘.

# s.interpolate('ffill', limit_direction='both')
# ValueError: `limit_direction` must be 'forward' for method `ffill`

# s.interpolate('bfill', limit_direction='both')
# ValueError: `limit_direction` must be 'backward' for method `bfill`

Dasselbe can SIE mit der Methode fillna() mit der Methode argument machen.

print(s.fillna(method='ffill'))
# 0    NaN
# 1    1.0
# 2    1.0
# 3    2.0
# 4    2.0
# dtype: float64

print(s.fillna(method='bfill'))
# 0    1.0
# 1    1.0
# 2    2.0
# 3    2.0
# 4    NaN
# dtype: float64

Spline-Interpolation:spline

Wenn method=’spline‘, wird eine Spline-Interpolation durchgeführt. Sie müssen die Argumentreihenfolge angeben.

s = pd.Series([0, 10, np.nan, np.nan, 4, np.nan],
              index=[0, 2, 5, 6, 8, 12])
print(s)
# 0      0.0
# 2     10.0
# 5      NaN
# 6      NaN
# 8      4.0
# 12     NaN
# dtype: float64

print(s.interpolate('spline', order=2))
# 0      0.00
# 2     10.00
# 5     13.75
# 6     12.00
# 8      4.00
# 12   -30.00
# dtype: float64

Die Spline-Interpolation verwendet immer den Index. Wenn sich der Index ändert, ändert sich auch das Ergebnis.

s.index = range(6)
print(s)
# 0     0.0
# 1    10.0
# 2     NaN
# 3     NaN
# 4     4.0
# 5     NaN
# dtype: float64

print(s.interpolate('spline', order=2))
# 0     0.0
# 1    10.0
# 2    14.0
# 3    12.0
# 4     4.0
# 5   -10.0
# dtype: float64

Daher erfordert die Spline-Interpolation, dass der Index aus Zahlen besteht. Wenn es sich um Zeichenfolgen handelt, WIRD ein Fehler ausgelöst.

s.index = list('abcdef')
print(s)
# a     0.0
# b    10.0
# c     NaN
# d     NaN
# e     4.0
# f     NaN
# dtype: float64

# print(s.interpolate('spline', order=2))
# ValueError: Index column must be numeric or datetime type when using spline method other than linear.
# Try setting a numeric or datetime index column before interpolating.

Andere

Es gibt andere Interpolationsmethoden, die für das Methodenargument angegeben werden können:'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'barycentric', 'krogh', 'polynomial', 'piecewise_polynomial', 'from_derivatives', 'pchip', 'akima'.

Wie in der offiziellen Dokumentation erwähnt, handelt es sich dabei um Wrapper für SciPy-Funktionen, einschließlich der oben erwähnten Spline-Interpolation („Spline“).

In allen Fällen muss der Index numerisch sein, wie bei der Spline-Interpolation.

Für Zeitreihendaten

method=’time‘ WIRD für Zeitreihendaten bereitgestellt. Bei method=’time‘ wird nach Datum und Uhrzeit der Indexspalte linear interpoliert.

df_nan = pd.DataFrame({'value': [1, pd.np.nan, pd.np.nan, pd.np.nan, 31]},
                      index=pd.to_datetime(['2018-01-01', '2018-01-02', '2018-01-15', '2018-01-20', '2018-01-31']))

print(df_nan)
#             value
# 2018-01-01    1.0
# 2018-01-02    NaN
# 2018-01-15    NaN
# 2018-01-20    NaN
# 2018-01-31   31.0

print(df_nan.interpolate())
#             value
# 2018-01-01    1.0
# 2018-01-02    8.5
# 2018-01-15   16.0
# 2018-01-20   23.5
# 2018-01-31   31.0

print(df_nan.interpolate('time'))
#             value
# 2018-01-01    1.0
# 2018-01-02    2.0
# 2018-01-15   15.0
# 2018-01-20   20.0
# 2018-01-31   31.0

Falls der Datentyp dtype Objekt ist (z. B. String)

Beispiel ist der Datentyp dtype Einer Spalte, die ein String-Element enthält, Objekt.

s_object = pd.Series(['A', np.nan, 'C'])
print(s_object)
# 0      A
# 1    NaN
# 2      C
# dtype: object

Die Objektspalte wird nicht durch method=’linear‘ (Standard) oder andere Methoden interpoliert. Es kann mit Methoden wie ffill, pad, bfill und backfill gefüllt werden, sterben die vorhandenen Werte verwenden.

print(s_object.interpolate())
# 0      A
# 1    NaN
# 2      C
# dtype: object

print(s_object.interpolate('ffill'))
# 0    A
# 1    A
# 2    C
# dtype: object

Dasselbe gilt, wenn das Element eine Zahl ist, der Datentyp jedoch ein Objekt ist.

s_object_num = pd.Series([0, np.nan, 2], dtype=object)
print(s_object_num)
# 0      0
# 1    NaN
# 2      2
# dtype: object

print(s_object_num.interpolate())
# 0      0
# 1    NaN
# 2      2
# dtype: object

print(s_object_num.interpolate('ffill'))
# 0    0
# 1    0
# 2    2
# dtype: int64

Wenn Sie es mit astype() in Float umwandeln, können Sie interpolieren. Beachten Sie, dass es nicht in int konvertiert werden kann, wenn es NaN enthält.

print(s_object_num.astype(float).interpolate())
# 0    0.0
# 1    1.0
# 2    2.0
# dtype: float64

# print(s_object_num.astype(int))
# ValueError: cannot convert float NaN to integer