0Pricing
Pandas & NumPy Academy · Lekcja

Uzupełnianie brakujących wartości

Zastąp NaN stałą, średnią kolumny, wartością z poprzedniego wiersza lub wartością z następnego wiersza za pomocą fillna() i jego parametru method.

Uzupełnianie brakujących wartości to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 3 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.

Wprowadzenie do fillna()

Imputacja oznacza zastępowanie brakujących wartości rozsądnymi zamiennikami zamiast usuwania wiersza. Podstawowym narzędziem Pandas służącym do tego celu jest fillna(): zastępuje ono każdą wartość NaN w obiekcie Series lub DataFrame określoną przez Państwa wartością. W przeciwieństwie do usuwania imputacja zachowuje wszystkie wiersze, co jest szczególnie ważne, gdy danych jest mało lub wzorzec braków zawiera istotne informacje.

Najprostsza postać polega na przekazaniu skalaru: df['col'].fillna(0).

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'product': ['A', 'B', 'C', 'D'],
    'price': [10.0, np.nan, 30.0, np.nan]
})

# Fill all NaN in 'price' with 0
filled = df['price'].fillna(0)
print(filled)
# 0    10.0
# 1     0.0
# 2    30.0
# 3     0.0

Uzupełnianie średnią lub medianą kolumny

Uzupełnianie kolumny za pomocą średniej (w przypadku rozkładów symetrycznych) lub mediany (w przypadku rozkładów skośnych) jest jedną z najczęściej stosowanych strategii imputacji. Statystyki te opisują tendencję centralną danych, dlatego ograniczają zniekształcenie rozkładu kolumny. Aby uniknąć wycieku danych, należy zawsze obliczać tę statystykę na zbiorze treningowym.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'salary': [50000, np.nan, 70000, 80000, np.nan, 60000]
})

mean_salary = df['salary'].mean()
median_salary = df['salary'].median()

df['salary_mean_filled'] = df['salary'].fillna(mean_salary)
df['salary_median_filled'] = df['salary'].fillna(median_salary)
print(df)
#     salary  salary_mean_filled  salary_median_filled
# 0  50000.0             50000.0               50000.0
# 1      NaN             65000.0               65000.0
# 2  70000.0             70000.0               70000.0

Uzupełnianie danych kategorycznych dominantą

W przypadku kolumn kategorycznych uzupełnianie średnią lub medianą nie ma sensu. Zamiast tego należy użyć dominanty — wartości występującej najczęściej. Series.mode()[0] zwraca najczęściej występującą wartość (element [0] obsługuje przypadek, w którym występuje kilka dominant).

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'status': ['active', 'inactive', None, 'active', None, 'active']
})

most_common = df['status'].mode()[0]
print('Mode:', most_common)  # active

df['status'] = df['status'].fillna(most_common)
print(df['status'].tolist())
# ['active', 'inactive', 'active', 'active', 'active', 'active']

Uzupełnianie w przód za pomocą ffill()

Uzupełnianie w przód (nazywane także last-observation-carried-forward, LOCF) propaguje ostatnią prawidłową wartość (inną niż NaN) w przód, aby uzupełnić kolejne pozycje NaN. Jest idealne w przypadku danych będących szeregiem czasowym, gdy pomiar pozostaje stały do momentu aktualizacji — na przykład dla statusu urządzenia, poziomów cen lub odczytów z czujników zmieniających się tylko podczas określonych zdarzeń.

import pandas as pd
import numpy as np

price = pd.Series(
    [100, np.nan, np.nan, 105, np.nan, 110],
    index=pd.date_range('2024-01', periods=6, freq='ME')
)

filled = price.ffill()
print(filled)
# 2024-01-31    100.0
# 2024-02-29    100.0
# 2024-03-31    100.0
# 2024-04-30    105.0
# 2024-05-31    105.0
# 2024-06-30    110.0

Uzupełnianie wstecz za pomocą bfill()

Uzupełnianie wstecz (next-observation-carried-backward, NOCB) propaguje następną prawidłową wartość wstecz, aby uzupełnić poprzedzające ją pozycje NaN. Jest przydatne, gdy wiadomo, że przyszłe dane uzupełnią brakujące wartości z przeszłości — na przykład gdy otrzymują Państwo dane na koniec miesiąca i muszą uzupełnić wstecz dni tego miesiąca, zanim raport zostanie dostarczony.

import pandas as pd
import numpy as np

df = pd.DataFrame({'value': [np.nan, np.nan, 3, np.nan, 5]})

print(df['value'].bfill())
# 0    3.0
# 1    3.0
# 2    3.0
# 3    5.0
# 4    5.0
# dtype: float64

Parametr limit dla uzupełniania w przód i wstecz

Zarówno ffill(), jak i bfill() przyjmują parametr limit, który ogranicza liczbę kolejnych wartości NaN podlegających uzupełnieniu. Jest to ważne, gdy chcą Państwo propagować wartość tylko przez krótki brak danych — długie przerwy powinny pozostać oznaczone jako NaN, aby wskazywać, że dane rzeczywiście są brakujące, a nie tylko opóźnione.

import pandas as pd
import numpy as np

s = pd.Series([1.0, np.nan, np.nan, np.nan, 5.0])

# Fill only the first NaN gap, leave the rest
print(s.ffill(limit=1))
# 0    1.0
# 1    1.0   <- filled
# 2    NaN   <- still NaN (limit reached)
# 3    NaN
# 4    5.0

Różne sposoby uzupełniania poszczególnych kolumn

W rzeczywistym obiekcie DataFrame różne kolumny mogą wymagać różnych strategii uzupełniania. Należy przekazać do fillna() słownik, w którym kluczami są nazwy kolumn, a wartościami — wartości używane do uzupełniania. Pozwala to zastosować imputację właściwą dla każdej kolumny w jednym wywołaniu, co jest czytelniejsze niż łączenie wielu pojedynczych wywołań fillna.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'age': [25, np.nan, 30],
    'income': [50000, np.nan, 70000],
    'country': ['USA', np.nan, 'UK']
})

fill_values = {
    'age': df['age'].median(),
    'income': df['income'].mean(),
    'country': 'Unknown'
}

filled = df.fillna(fill_values)
print(filled)
#     age   income  country
# 0  25.0  50000.0      USA
# 1  27.5  60000.0  Unknown
# 2  30.0  70000.0       UK

Imputacja uwzględniająca grupy

Bardziej zaawansowana strategia polega na uzupełnianiu wartości NaN za pomocą średniej lub mediany dla grupy, a nie średniej dla całej kolumny. Można na przykład uzupełnić brakujące wynagrodzenie medianą wynagrodzeń dla danej kategorii stanowiska. Pozwala to zachować strukturę podgrup i uzyskać bardziej realistyczne uzupełnienia niż w przypadku statystyki globalnej.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'dept': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
    'salary': [90000, np.nan, 50000, np.nan, 110000]
})

# Fill salary NaN with the median salary for each department
df['salary'] = df.groupby('dept')['salary'].transform(
    lambda x: x.fillna(x.median())
)
print(df)
#    dept   salary
# 0   Eng  90000.0
# 1   Eng  100000.0   <- group median (90k+110k)/2
# 2    HR  50000.0
# 3    HR  50000.0
# 4   Eng  110000.0

Uzupełnianie stałą wartością zastępczą

Czasami właściwym sposobem imputacji jest wartość zastępcza, która sygnalizuje „nieznane”, a nie rzeczywisty pomiar. Może to być na przykład -1 dla nieznanego wieku, „N/A” dla nieznanej kategorii lub False dla nieznanej wartości logicznej. Wartości zastępcze są właściwe wtedy, gdy kod używany w dalszej części przetwarzania jawnie je sprawdza i traktuje inaczej niż rzeczywiste dane.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'referral_source': ['email', np.nan, 'ad'],
    'trial_days': [14, np.nan, 7]
})

df['referral_source'] = df['referral_source'].fillna('unknown')
df['trial_days'] = df['trial_days'].fillna(-1).astype(int)
print(df)
#    user_id referral_source  trial_days
# 0        1           email          14
# 1        2         unknown          -1
# 2        3              ad           7

Łączenie wywołań fillna() w potoku

Podobnie jak wszystkie metody Pandas, fillna() zwraca nowy obiekt DataFrame i dobrze integruje się z łańcuchem metod. Wywołanie .fillna() po .dropna() stosuje strategię dwuetapową: usuwa wiersze pozbawione kluczowych kolumn, a następnie uzupełnia pozostałe opcjonalne wartości NaN rozsądnymi wartościami domyślnymi — wszystko w jednym czytelnym potoku.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'user_id': [1, None, 3, 4],
    'score': [88, 95, np.nan, 76],
    'label': ['A', 'B', None, 'D']
})

cleaned = (
    df
    .dropna(subset=['user_id'])
    .fillna({'score': df['score'].mean(), 'label': 'Unknown'})
)
print(cleaned)
#    user_id  score    label
# 0      1.0   88.0        A
# 2      3.0   86.3  Unknown
# 3      4.0   76.0        D

Sprawdzanie, czy nie pozostały wartości NaN

Po imputacji należy zawsze sprawdzić, czy w docelowych kolumnach nie pozostały wartości NaN. Należy wywołać df.isna().sum() lub sprawdzić asercją, że liczba wynosi zero. Nieoczekiwana wartość różna od zera oznacza, że wywołanie fillna nie obsłużyło któregoś przypadku — być może kolumna miała typ danych uniemożliwiający uzupełnienie albo pominięto ją w słowniku.

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [1.0, np.nan, 3.0], 'b': [np.nan, 2.0, 3.0]})
filled = df.fillna(0)

# Verify
assert filled.isna().sum().sum() == 0, 'Some NaN remain!'
print('All NaN filled successfully')
print(filled.isna().sum())
# a    0
# b    0
# dtype: int64

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat uzupełniania brakujących wartości w Pandas.

Podsumowanie lekcji

W tej lekcji nauczyłeś się, że: fillna(scalar) zastępuje wszystkie wartości NaN stałą, fillna(mean/median) uzupełnia braki za pomocą statystyk kolumny, a ffill()/bfill() propagują sąsiednie wartości w szeregach czasowych. Przekaż słownik do fillna(), aby zastosować strategie właściwe dla poszczególnych kolumn, oraz użyj groupby().transform() do imputacji uwzględniającej grupy. W następnej części omówimy interpolację oraz sytuacje, w których warto wybrać zaawansowane techniki imputacji.

Często zadawane pytania

Czy lekcja „Uzupełnianie brakujących wartości” jest bezpłatna?

Tak — pełny tekst „Uzupełnianie brakujących wartości” 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 „Uzupełnianie brakujących wartości”?

Zastąp NaN stałą, średnią kolumny, wartością z poprzedniego wiersza lub wartością z następnego wiersza za pomocą fillna() i jego parametru method. Ć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 3 z 4.

Ile czasu zajmuje lekcja „Uzupełnianie brakujących wartości”?

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

  1. Wykrywanie brakujących wartości
  2. Usuwanie brakujących wartości
  3. Uzupełnianie brakujących wartości
  4. Interpolacja i zaawansowane uzupełnianie
← Powrót do Pandas & NumPy Academy