Interpolacja i zaawansowane uzupełnianie
Użyj interpolate() do płynnego uzupełniania danych zależnych od czasu i dowiedz się, kiedy odpowiednie jest uzupełnianie średnią, a kiedy medianą.
Interpolacja i zaawansowane uzupełnianie to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.
Kiedy interpolacja jest lepsza niż fillna()
Uzupełnianie w przód i wstecz przenosi najbliższą znaną wartość bez uwzględniania trendu danych. Interpolacja szacuje brakujące wartości, zakładając płynne przejście między znanymi wartościami — na przykład jeśli temperatura wynosiła 20°C w poniedziałek i 30°C w piątek, interpolacja oszacuje 25°C w środę. Zapewnia to bardziej realistyczną imputację w przypadku płynnie zmieniających się sygnałów, takich jak dane z czujników, ceny lub liczebność populacji.
import pandas as pd
import numpy as np
df = pd.DataFrame({
'day': [1, 2, 3, 4, 5],
'temp': [20.0, np.nan, np.nan, np.nan, 30.0]
})
# Linear interpolation fills gaps smoothly
df['temp_interp'] = df['temp'].interpolate(method='linear')
print(df)
# day temp temp_interp
# 0 1 20.0 20.0
# 1 2 NaN 22.5
# 2 3 NaN 25.0
# 3 4 NaN 27.5
# 4 5 30.0 30.0Metody interpolate()
Metoda Pandas interpolate() obsługuje wiele metod. Najczęściej używane to 'linear' (wartości rozmieszczone równomiernie między znanymi wartościami), 'time' (uwzględnia nierówne odstępy czasu, gdy ustawiono DatetimeIndex), 'polynomial' (dopasowuje krzywą wielomianową i wymaga argumentu order) oraz 'spline' (wygładzony wielomian odcinkowy). Metoda liniowa jest najbezpieczniejszym wyborem domyślnym; metody wyższych rzędów mogą prowadzić do nadmiernego dopasowania w przypadku małych luk.
import pandas as pd
import numpy as np
s = pd.Series([0, np.nan, np.nan, 8.0])
print('linear:', s.interpolate('linear').tolist())
# [0.0, 2.6666..., 5.3333..., 8.0]
print('polynomial(2):', s.interpolate('polynomial', order=2).tolist())
# [0.0, 2.222..., 5.111..., 8.0]Interpolacja time z użyciem DatetimeIndex
Gdy obiekt Series ma DatetimeIndex z nierównymi odstępami czasu (np. obejmuje tylko dni robocze i pomija weekendy), method='time' interpoluje proporcjonalnie do rzeczywiście upływającego czasu, a nie tylko na podstawie pozycji. Jest to dokładniejsze niż interpolacja liniowa, która traktuje każdy wiersz jako równomiernie rozmieszczony, niezależnie od przerwy w kalendarzu.
import pandas as pd
import numpy as np
# Unequal gaps: Jan 1, Jan 3, Jan 10
idx = pd.to_datetime(['2024-01-01', '2024-01-03', '2024-01-10'])
s = pd.Series([100.0, np.nan, 170.0], index=idx)
# linear treats gaps as equal (position-based)
print(s.interpolate('linear').tolist()) # [100.0, 135.0, 170.0]
# time accounts for actual day count
# Jan 1 to Jan 3 = 2 days, Jan 1 to Jan 10 = 9 days
# fraction: 2/9 of the way from 100 to 170
print(s.interpolate('time').tolist()) # [100.0, 115.55..., 170.0]Ograniczanie zakresu interpolacji
Podobnie jak ffill(), interpolate() przyjmuje parametr limit, który ogranicza liczbę kolejnych pozycji NaN podlegających uzupełnieniu. Pozostałe wartości NaN po przekroczeniu limitu pozostają brakujące. Zapobiega to interpolowaniu przez bardzo długie przerwy, w których rzeczywista wartość mogłaby być dowolna — długie przerwy należy oznaczyć do ręcznej weryfikacji.
import pandas as pd
import numpy as np
s = pd.Series([1.0, np.nan, np.nan, np.nan, np.nan, 10.0])
# Only fill the first 2 NaN positions
filled = s.interpolate('linear', limit=2)
print(filled.tolist())
# [1.0, 2.8, 4.6, NaN, NaN, 10.0]Wybór imputacji średnią lub medianą
Imputacja średnią i medianą jest prosta, ale wiąże się z istotnymi kompromisami. Średnia jest wrażliwa na wartości odstające — kilka bardzo dużych wartości podnosi jej poziom, przez co jest ona kiepskim uzupełnieniem dla rozkładu prawoskośnego, takiego jak rozkład dochodów lub cen nieruchomości. Mediana jest odporna na wartości odstające i stanowi lepszy wybór dla skośnych kolumn. Średniej należy używać tylko wtedy, gdy dane są w przybliżeniu symetryczne i nie zawierają skrajnych wartości odstających.
import pandas as pd
import numpy as np
# Skewed income data with an outlier
income = pd.Series([30000, 35000, 32000, 1_000_000, np.nan])
print('Mean: ', income.mean()) # ~274000 — pulled by outlier
print('Median:', income.median()) # ~33500 — robust choice
# Prefer median for skewed data
filled = income.fillna(income.median())
print(filled.tolist())
# [30000, 35000, 32000, 1000000, 33500.0]Koncepcja imputacji KNN
Imputacja metodą K-Nearest Neighbour (KNN) zastępuje brakującą wartość średnią (lub średnią ważoną) z k najbardziej podobnych wierszy, mierzonych odległością wzdłuż niebrakujących cech. Jest to strategia wielowymiarowa — wykorzystuje informacje z innych kolumn do określenia sposobu uzupełnienia, dzięki czemu przy skorelowanych cechach jest dokładniejsza niż imputacja średnią z pojedynczej kolumny.
Scikit-learn's KNNImputer integruje się bezpośrednio z tablicami NumPy i obiektami DataFrame biblioteki Pandas.
import pandas as pd
import numpy as np
from sklearn.impute import KNNImputer
df = pd.DataFrame({
'age': [25, 35, np.nan, 45],
'income': [50000, 70000, 60000, np.nan]
})
imputer = KNNImputer(n_neighbors=2)
df_imputed = pd.DataFrame(
imputer.fit_transform(df),
columns=df.columns
)
print(df_imputed.round(1))
# age income
# 0 25.0 50000.0
# 1 35.0 70000.0
# 2 30.0 60000.0 <- filled from neighbours
# 3 45.0 65000.0 <- filled from neighboursWielokrotna imputacja za pomocą IterativeImputer
Wielokrotna imputacja jest uznawana za najlepszą metodę obsługi brakujących danych w badaniach statystycznych. Narzędzie Scikit-learn IterativeImputer implementuje podejście MICE (Multiple Imputation by Chained Equations): modeluje każdą kolumnę zawierającą braki jako funkcję pozostałych kolumn i iteracyjnie wykonuje imputację do momentu ustabilizowania się wartości. Dzięki temu lepiej odwzorowuje zależności między cechami niż strategie wykorzystujące pojedyncze kolumny.
import pandas as pd
import numpy as np
from sklearn.experimental import enable_iterative_imputer # noqa
from sklearn.impute import IterativeImputer
df = pd.DataFrame({
'x1': [1, 2, np.nan, 4, 5],
'x2': [2, np.nan, 6, 8, 10],
'y': [3, 5, 7, np.nan, 11]
})
imp = IterativeImputer(max_iter=10, random_state=0)
df_filled = pd.DataFrame(imp.fit_transform(df), columns=df.columns)
print(df_filled.round(2))Kolumny wskaźnikowe dla brakujących danych
Zamiast ukrywać fakt, że wartość została imputowana, dobrą praktyką jest dodanie binarniej kolumny wskaźnikowej, która oznacza wiersze zawierające brakujące wartości przed imputacją. Dzięki temu modele używane w dalszej części przetwarzania mogą uczyć się na podstawie samego wzorca braków — czasami informacja o tym, że wartości brakuje, ma taką samą moc predykcyjną jak sama wartość.
import pandas as pd
import numpy as np
df = pd.DataFrame({'salary': [50000, np.nan, 70000, np.nan, 90000]})
# Add indicator before filling
df['salary_was_missing'] = df['salary'].isna().astype(int)
# Then fill
df['salary'] = df['salary'].fillna(df['salary'].median())
print(df)
# salary salary_was_missing
# 0 50000.0 0
# 1 70000.0 1
# 2 70000.0 0
# 3 70000.0 1
# 4 90000.0 0Imputacja a wyciek danych
Kluczowa zasada w potokach uczenia maszynowego: statystyki używane do imputacji (średnią, medianę, dominantę) należy obliczać wyłącznie na zbiorze treningowym, a następnie stosować te same wartości do zbioru testowego. Obliczenie statystyk na całym zbiorze danych przed jego podziałem powoduje wyciek danych — model pośrednio widzi dane testowe podczas treningu, co zawyża szacowaną skuteczność. Zawsze należy dopasowywać imputery do danych treningowych, a następnie transformować zarówno zbiór treningowy, jak i testowy.
import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
df = pd.DataFrame({'feature': [1, 2, np.nan, 4, np.nan, 6, 7, 8]})
train, test = train_test_split(df, test_size=0.25, random_state=0)
# Fit ONLY on training data
imp = SimpleImputer(strategy='mean')
train['feature'] = imp.fit_transform(train[['feature']])
# Transform test using training statistics
test['feature'] = imp.transform(test[['feature']])
print('Train mean used:', imp.statistics_[0])Wizualne porównywanie strategii imputacji
Po zastosowaniu wielu metod imputacji należy porównać ich wpływ, przedstawiając obok siebie rozkłady oryginalnych i imputowanych kolumn. Dobra imputacja powinna możliwie wiernie zachowywać kształt rozkładu oryginalnego (średnią, wariancję i skośność). Imputacja średnią zawęża rozkład, natomiast KNN i MICE zwykle lepiej go zachowują.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
original = np.random.exponential(scale=5, size=200)
with_nan = original.copy()
with_nan[np.random.choice(200, 40, replace=False)] = np.nan
s = pd.Series(with_nan)
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
s.dropna().hist(ax=axes[0], bins=20, title='Original (no NaN)')
s.fillna(s.mean()).hist(ax=axes[1], bins=20, title='Mean-imputed')
plt.tight_layout()
plt.savefig('imputation_comparison.png')
print('Saved comparison chart')Wybór właściwej strategii imputacji
Nie istnieje jedna uniwersalnie najlepsza strategia imputacji — właściwy wybór zależy od kontekstu. Średnią lub medianę należy stosować w prostych przypadkach jednowymiarowych, przy niewielkiej liczbie braków. ffill/bfill sprawdza się w szeregach czasowych o stabilnych trendach. KNN lub IterativeImputer warto stosować, gdy cechy są skorelowane i chcą Państwo wykorzystać istniejące między nimi zależności. Stałe wartości wynikające z dziedziny (np. 0 dla braku, -1 dla wartości nieznanej) należy wybierać, gdy brakująca wartość ma jasne znaczenie biznesowe. Zawsze należy udokumentować swój wybór.
# Decision guide (no runnable code)
#
# Missing < 5% AND data is MCAR? -> Mean/median fill is fine
# Time series with stable trend? -> ffill() with limit
# Features are correlated? -> KNNImputer or IterativeImputer
# Categorical column? -> Mode fill or 'Unknown' sentinel
# Going into ML model? -> Add indicator column + fill
# Research / publication quality? -> Multiple imputation (MICE)
print('Strategy selected based on context')Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat interpolacji i zaawansowanej imputacji.
Podsumowanie lekcji
W tej lekcji nauczyłeś się, że: interpolate() szacuje brakujące wartości, zakładając płynny trend między znanymi wartościami, method='time' obsługuje nierówne odstępy w DatetimeIndex, a zaawansowane strategie, takie jak KNNImputer i IterativeImputer, wykorzystują inne kolumny do określania sposobu uzupełniania. Przed imputacją zawsze należy dodać kolumny wskaźnikowe, a statystyki dopasowywać wyłącznie na zbiorze treningowym, aby uniknąć wycieku danych. W następnej części zajmiemy się sprawdzaniem i konwersją typów danych kolumn obiektu DataFrame.
Ucz się Python dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 30
- Lekcje
- 120
Często zadawane pytania
Czy lekcja „Interpolacja i zaawansowane uzupełnianie” jest bezpłatna?
Tak — pełny tekst „Interpolacja i zaawansowane uzupełnianie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Interpolacja i zaawansowane uzupełnianie”?
Użyj interpolate() do płynnego uzupełniania danych zależnych od czasu i dowiedz się, kiedy odpowiednie jest uzupełnianie średnią, a kiedy medianą. Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?
Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Interpolacja i zaawansowane uzupełnianie”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?
Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wykrywanie brakujących wartości
- Usuwanie brakujących wartości
- Uzupełnianie brakujących wartości
- Interpolacja i zaawansowane uzupełnianie