
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
- Zeile oder Spalte:
- Interpolationsmethode:
method
- Lineare Interpolation:
linear, index, values
- Vorhandene Werte verwenden:
ffill, pad, bfill, backfill
- Spline-Interpolation:
spline
- Andere
- Lineare Interpolation:
- 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