0Pricing
Pandas & NumPy Academy · Lekcja

Czyszczenie danych i inżynieria cech

Zastosuj zaawansowaną listę kontrolną czyszczenia, utwórz cechy dat i kolumny ze wskaźnikami oraz zweryfikuj oczyszczony zbiór danych za pomocą asercji.

Czyszczenie danych i inżynieria cech to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 2 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.

Wczytywanie skontrolowanego zbioru danych

Kontynuując projekt końcowy, wczytaj czysty punkt kontrolny Parquet zapisany w poprzednim kroku. Oddziela to etap czyszczenia od pozyskiwania danych — możesz iterować nad logiką czyszczenia bez ponownego wykonywania powolnych operacji scalania i parsowania. Wczytaj plik clean_orders Parquet i sprawdź, czy liczba wierszy oraz typy danych są zgodne z oczekiwaniami określonymi w podsumowaniu audytu. Plik Parquet zachowuje wszystkie typy danych, w tym kolumny kategoryczne, więc ponowne rzutowanie nie jest potrzebne.

import pandas as pd

# Load from checkpoint
df = pd.read_parquet('output/clean_orders.parquet')
print(f'Loaded: {df.shape}')
print(df.dtypes)
print(f'Date range: {df["order_date"].min().date()} to {df["order_date"].max().date()}')

Stosowanie zaawansowanej listy kontrolnej czyszczenia

Po wczytaniu scalonego zbioru danych zastosuj zaawansowaną listę kontrolną czyszczenia: usuń dokładne i częściowe duplikaty w order_id, ogranicz wartości odstające w unit_price za pomocą metody IQR, ujednolić niespójne wartości category (np. 'Electronics', 'electronics' i 'ELECTRONIC') oraz sprawdź, czy quantity × unit_price jest zawsze dodatnie dla zwykłych zamówień. Każdy krok jest funkcją, która przyjmuje i zwraca DataFrame, dzięki czemu potok można testować i odwracać.

import pandas as pd
import numpy as np

def remove_duplicates(df):
    n_before = len(df)
    df = df.drop_duplicates(subset=['order_id'], keep='first')
    print(f'Duplicates removed: {n_before - len(df)}')
    return df

def standardise_categories(df):
    df['category'] = (df['category']
                      .astype(str)
                      .str.strip()
                      .str.title())
    return df

def cap_price_outliers(df):
    q1, q3 = df['unit_price'].quantile([0.25, 0.75])
    iqr = q3 - q1
    upper = q3 + 3 * iqr
    df['unit_price'] = df['unit_price'].clip(upper=upper)
    return df

df = remove_duplicates(df)
df = standardise_categories(df)
df = cap_price_outliers(df)
print('Cleaning complete.')

Tworzenie cech daty

Wyodrębnij cechy czasowe z daty zamówienia za pomocą akcesora .dt. Utwórz kolumny year, month, quarter, day_of_week i week_of_year. Cechy te służą do analiz grupowanych groupby (np. przychód miesięczny), filtrowania według czasu (tylko Q3) oraz tworzenia wizualizacji. Utwórz również kolumnę tekstową year_month (np. '2024-06'), która będzie czytelną dla człowieka etykietą okresu na osiach wykresów.

import pandas as pd

df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['quarter'] = df['order_date'].dt.quarter
df['day_of_week'] = df['order_date'].dt.dayofweek  # 0=Monday
df['week'] = df['order_date'].dt.isocalendar().week.astype('int32')
df['year_month'] = df['order_date'].dt.to_period('M').astype(str)

print('Date features created:')
print(df[['order_date', 'year', 'month', 'quarter', 'year_month']].head())

Obliczanie przychodu z pozycji zamówienia

Najbardziej podstawową cechą w zbiorze danych sprzedażowych jest przychód z pozycji zamówienia: revenue = quantity × unit_price. Utwórz ją jako nową kolumnę. Jeśli dostępne są dane o kosztach, utwórz również kolumnę gross_margin: margin = (price - cost) / price. Te kolumny pochodne są podstawą wszystkich KPI dotyczących przychodów. Zawsze używaj zwektoryzowanych operacji na kolumnach zamiast pętli — pojedyncze przypisanie dla całej kolumny jest wielokrotnie szybsze niż iterowanie wiersz po wierszu.

import pandas as pd

# Line-item revenue
df['revenue'] = (df['quantity'] * df['unit_price']).astype('float32')

# Gross margin (if unit_cost column exists)
if 'unit_cost' in df.columns:
    df['gross_margin'] = (df['unit_price'] - df['unit_cost']) / df['unit_price']

# Discount flag: orders with more than 20% off list price
if 'list_price' in df.columns:
    df['is_discounted'] = df['unit_price'] < df['list_price'] * 0.8

print('Revenue stats:')
print(df['revenue'].describe().round(2))

Przypisywanie klientów do kohort

Kohorta to grupa klientów mających wspólną cechę — zazwyczaj okres, w którym dokonali pierwszego zakupu. Przypisz każdego klienta do jego kohorty pozyskania, znajdując datę jego pierwszego zamówienia. Użyj groupby('customer_id')['order_date'].min(), aby obliczyć datę pierwszego zamówienia każdego klienta, a następnie utwórz kolumnę cohort_month, konwertując ją na okres rok-miesiąc. Ta etykieta kohorty będzie podstawą macierzy retencji w następnej lekcji.

import pandas as pd

# First purchase date per customer
first_purchase = (
    df.groupby('customer_id')['order_date']
    .min()
    .dt.to_period('M')
    .astype(str)
    .rename('cohort_month')
)

# Merge back onto orders
df = df.merge(first_purchase, on='customer_id', how='left')
print('Cohort distribution (top 5):')
print(df['cohort_month'].value_counts().head())
print(f'Distinct cohorts: {df["cohort_month"].nunique()}')

Cechy wartości klienta w całym okresie współpracy

Oblicz cechy podsumowujące na poziomie klienta: łączną liczbę zamówień, łączny przychód, średnią wartość zamówienia, liczbę dni od pierwszego i ostatniego zakupu oraz liczbę różnych zakupionych kategorii. Scal je z powrotem z głównym DataFrame jako kolumny wzbogacające na poziomie klienta. Cechy te służą do segmentacji (np. klientów o wysokiej i niskiej wartości) oraz jako dane wejściowe do modeli uczenia maszynowego przewidujących odejście klienta lub prawdopodobieństwo sprzedaży dodatkowej.

import pandas as pd

customer_stats = df.groupby('customer_id').agg(
    total_orders=('order_id', 'nunique'),
    total_revenue=('revenue', 'sum'),
    avg_order_value=('revenue', 'mean'),
    categories_purchased=('category', 'nunique'),
    first_order=('order_date', 'min'),
    last_order=('order_date', 'max')
).reset_index()

customer_stats['days_as_customer'] = (
    (customer_stats['last_order'] - customer_stats['first_order'])
    .dt.days
)

print(customer_stats.describe().round(2))

Walidacja schematu za pomocą asercji

Po przygotowaniu cech uruchom asercje walidacji schematu, aby potwierdzić, że dane spełniają oczekiwania przed przekazaniem ich do etapu analizy. Sprawdź, czy istnieją wszystkie oczekiwane kolumny, przychód jest nieujemny dla zwykłych zamówień, cohort_month nie zawiera wartości null, a year_month odpowiada rokowi analizy. Asercje te działają jak kontrakt: jeśli którakolwiek z nich się nie powiedzie, potok natychmiast się zatrzyma i wyświetli jasny komunikat o błędzie, zamiast po cichu generować nieprawidłowe wyniki.

import pandas as pd

def validate_clean_df(df):
    required_cols = ['order_id', 'customer_id', 'revenue', 'year_month',
                     'cohort_month', 'category', 'region', 'order_date']
    missing = [c for c in required_cols if c not in df.columns]
    assert not missing, f'Missing columns: {missing}'

    assert (df['revenue'] >= 0).all(), 'Negative revenue found'
    assert df['cohort_month'].notna().all(), 'Null cohort_month values'
    assert df['order_date'].notna().all(), 'Null order dates'
    print(f'Validation passed: {len(df):,} rows, {len(df.columns)} columns')

validate_clean_df(df)

Obsługa kategorii o małej częstości występowania

W rzeczywistych zbiorach danych niektóre kategorie lub regiony pojawiają się tylko kilka razy — zbyt mało, aby umożliwić miarodajną analizę. Zastąp wartości o małej częstości występowania wartością 'Other', aby uniknąć wykresów zaśmieconych dziesiątkami kategorii reprezentowanych przez pojedyncze zamówienia. Praktyczny próg: wartości występujące w mniej niż 0,5% wierszy są łączone. Jest to również ważne w uczeniu maszynowym: kodowanie one-hot 200 rzadkich kategorii marnuje pamięć i wprowadza szum.

import pandas as pd

def collapse_rare_values(df, col, min_pct=0.005):
    threshold = len(df) * min_pct
    counts = df[col].value_counts()
    rare = counts[counts < threshold].index
    n_rare = len(rare)
    df[col] = df[col].apply(lambda x: 'Other' if x in rare else x)
    print(f'{col}: collapsed {n_rare} rare values into "Other"')
    return df

df = collapse_rare_values(df, 'category', min_pct=0.005)
df = collapse_rare_values(df, 'region', min_pct=0.005)
print('Category distribution after collapsing:')
print(df['category'].value_counts())

Zapisywanie zbioru danych z przygotowanymi cechami

Zapisz w pełni oczyszczony DataFrame z przygotowanymi cechami jako punkt kontrolny Parquet. Jest to zbiór danych gotowy do analizy — wynik wszystkich etapów pozyskiwania danych, czyszczenia i przygotowywania cech. Kolejne etapy potoku (obliczanie KPI, wizualizacja, raportowanie) odczytują dane z tego punktu kontrolnego. Punkt kontrolny pełni również funkcję rezultatu, który można udostępnić członkom zespołu lub przesłać do data lake, aby inni mogli odpytywać go za pomocą SQL albo Pandas.

import pandas as pd

# Convert category columns back to Categorical for memory efficiency
for col in ['category', 'region', 'acquisition_channel']:
    if col in df.columns:
        df[col] = df[col].astype('category')

# Save analysis-ready dataset
df.to_parquet('output/analysis_ready.parquet', index=False)

# Also save customer stats for segmentation
customer_stats.to_parquet('output/customer_stats.parquet', index=False)

print(f'Analysis-ready dataset: {df.shape}')
print(f'Memory usage: {df.memory_usage(deep=True).sum()/1e6:.1f} MB')

Podsumowanie przygotowywania cech

Dobre przygotowywanie cech równoważy zwiększanie sygnału predykcyjnego z zachowaniem czytelności i możliwości testowania potoku. Cechy utworzone na tym etapie — przychód, składowe daty, cohort_month, statystyki klientów i połączone kategorie — wynikały z celów analizy określonych podczas konfiguracji projektu. Nie ulegaj pokusie tworzenia dziesiątek cech na wszelki wypadek. W przypadku każdej cechy zadaj sobie pytanie: czy zostanie użyta w co najmniej jednym KPI lub na jednej wizualizacji? Jeśli nie, odłóż jej utworzenie. Zbiór danych gotowy do analizy powinien być zwięzły i celowy.

import pandas as pd

# Summary of engineered features
df = pd.read_parquet('output/analysis_ready.parquet')

original_cols = ['order_id', 'customer_id', 'order_date', 'quantity', 'unit_price']
engineered_cols = [c for c in df.columns if c not in original_cols]

print('Original columns:', original_cols)
print('Engineered features:', engineered_cols)
print(f'Total columns: {len(df.columns)}')
print(f'Total rows: {len(df):,}')

Dokumentowanie decyzji w kodzie

W przypadku każdej nieoczywistej decyzji dotyczącej czyszczenia lub przygotowywania cech dodaj komentarz wyjaśniający jej przyczynę. Ty w przyszłości (lub członek zespołu) nie będzie pamiętać, dlaczego ustawiono mnożnik IQR na 3 zamiast 1,5 ani dlaczego jako próg rzadkiej kategorii przyjęto 0,5%. Komentarze w kodzie oraz dziennik decyzji (prosta lista w pliku README projektu lub w pliku Markdown) ułatwiają utrzymanie i audytowanie potoku. Czysty, udokumentowany kod jest właściwym rezultatem — pliki wyjściowe są tylko jego konsekwencją.

# Engineering decisions log
DECISIONS = '''
# Data Cleaning & Feature Engineering Decisions

## Duplicate handling
Kept first occurrence of duplicate order_id (most likely the original order).

## Outlier capping
Unit price capped at Q3 + 3*IQR (not 1.5*IQR) because price distribution
has legitimate high-value enterprise orders that should not be removed.

## Rare category threshold: 0.5%
Values below 0.5% of total orders collapsed to "Other" to keep charts readable
and avoid spurious significance in category-level tests.

## Cohort assignment
Cohort = first purchase calendar month (not signup month), because many users
sign up but do not purchase until months later.
'''
print(DECISIONS)

Szybki test

Sprawdź swoją wiedzę na temat koncepcji analizy danych przedstawionych w tej lekcji.

Podsumowanie lekcji

W tej lekcji nauczyłeś się, że: modułowe funkcje czyszczenia (usuwanie duplikatów, ograniczanie wartości odstających, ujednolicanie kategorii) przyjmują i zwracają DataFrame, co ułatwia ich testowanie, przygotowywanie cech pozwoliło utworzyć składowe daty, przychód z pozycji zamówienia, kohorty klientów i statystyki podsumowujące, a asercje walidacji schematu zabezpieczają przejście od czyszczenia do analizy. Następnie obliczymy najważniejsze KPI projektu: miesięczną retencję kohort, przychód produktów i krocząco aktywnych użytkowników.

Często zadawane pytania

Czy lekcja „Czyszczenie danych i inżynieria cech” jest bezpłatna?

Tak — pełny tekst „Czyszczenie danych i inżynieria cech” 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 „Czyszczenie danych i inżynieria cech”?

Zastosuj zaawansowaną listę kontrolną czyszczenia, utwórz cechy dat i kolumny ze wskaźnikami oraz zweryfikuj oczyszczony zbiór danych za pomocą asercji. Ć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 2 z 4.

Ile czasu zajmuje lekcja „Czyszczenie danych i inżynieria cech”?

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. Konfiguracja projektu i wczytywanie danych
  2. Czyszczenie danych i inżynieria cech
  3. Analiza i obliczanie KPI
  4. Końcowa wizualizacja i eksport raportu
← Powrót do Pandas & NumPy Academy