Walidacja schematu i asercje
Pisz asercje sprawdzające zakresy kolumn, ograniczenia wartości niepustych i unikatowe klucze, uruchamiane na początku każdego potoku.
Walidacja schematu i asercje 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.
Dlaczego walidacja schematu ma znaczenie
Potok danych przetwarza nowe dane automatycznie, często bez udziału człowieka. Jeśli schemat pliku wejściowego się zmieni — kolumna zostanie przemianowana, format daty ulegnie zmianie albo pojawi się nowa kategoria — potok powinien wyraźnie zgłosić błąd, zamiast generować po cichu niepoprawne wyniki. Walidacja schematu za pomocą asercji to mechanizm egzekwujący kontrakty między producentami a odbiorcami danych i wykrywający problemy możliwie najwcześniej.
import pandas as pd
import numpy as np
df = pd.read_parquet('sales_treated.parquet')
print('Loaded:', df.shape)
print(df.dtypes)Sprawdzanie wymaganych kolumn
Najbardziej podstawowa walidacja polega na sprawdzeniu, czy obecne są wszystkie wymagane kolumny. Oczekiwany zbiór kolumn należy przechowywać w konfiguracji i sprawdzać asercją, czy jest podzbiorem rzeczywistych kolumn. Kontrola ta natychmiast wykrywa zmiany nazw i usunięcia kolumn na początku potoku, zanim dalszy kod spróbuje uzyskać dostęp do brakujących kolumn i zgłosi mylący błąd KeyError głęboko wewnątrz potoku.
REQUIRED_COLUMNS = {'order_id', 'order_date', 'customer_id',
'product', 'category', 'quantity', 'unit_price', 'revenue'}
missing = REQUIRED_COLUMNS - set(df.columns)
assert not missing, f'Missing required columns: {missing}'
print('All required columns present.')Asercje dotyczące typów danych kolumn
Po sprawdzeniu wymaganych kolumn należy zweryfikować ich typy danych. Kolumna dat załadowana jako object oznacza, że nie wywołano pd.to_datetime(). Kolumna identyfikatora przechowywana jako float zamiast int64 często wskazuje na obecność wartości NaN, które uniemożliwiły przechowywanie danych w typie całkowitym. Dla najważniejszych kolumn należy zapisać asercje typów za pomocą assert df['col'].dtype == expected_type.
assert pd.api.types.is_datetime64_any_dtype(df['order_date']), \
'order_date must be datetime'
assert pd.api.types.is_numeric_dtype(df['revenue']), \
'revenue must be numeric'
assert df['order_id'].dtype == object or pd.api.types.is_integer_dtype(df['order_id']), \
'order_id must be string or int'
print('Dtype checks passed.')Ograniczenia dotyczące wartości null
Kluczowe kolumny, takie jak order_id, order_date i revenue, nigdy nie powinny zawierać wartości null. Dla każdej z nich należy użyć asercji df['col'].notna().all(). Aby komunikat asercji ułatwiał podjęcie działania, należy uwzględnić liczbę wartości null, tak aby operator potoku znał skalę problemu, a nie tylko informację o niepowodzeniu asercji.
NOT_NULL_COLS = ['order_id', 'order_date', 'revenue', 'customer_id']
for col in NOT_NULL_COLS:
null_count = df[col].isna().sum()
assert null_count == 0, f'{col} has {null_count} null values'
print('Non-null checks passed.')Sprawdzanie zakresów kolumn liczbowych
Kolumny liczbowe często mają prawidłowe zakresy wynikające z reguł biznesowych. Przychód musi być nieujemny. Ilość musi być dodatnią liczbą całkowitą. Cena jednostkowa musi być większa od zera. Należy jawnie sprawdzić te ograniczenia — wiersz z ujemnym przychodem, który przejdzie dalej, zaniży sumy we wszystkich kolejnych agregacjach bez zgłoszenia jakiegokolwiek błędu. Kontrola zakresów wcześnie wykrywa błędy wprowadzania danych i usterki systemów nadrzędnych.
assert (df['revenue'] >= 0).all(), 'Negative revenue found'
assert (df['quantity'] > 0).all() or df['is_return'].any(), \
'Non-positive quantity without return flag'
assert (df['unit_price'] > 0).all(), 'Zero or negative unit price found'
print('Range checks passed.')Asercje dotyczące unikalnych kluczy
Po usunięciu duplikatów wartość order_id powinna być unikalna. Należy użyć asercji df['order_id'].is_unique, aby sprawdzić, czy ta niezmienniczość jest zachowana przy każdym uruchomieniu potoku. Naruszenie unikalności po usunięciu duplikatów wskazuje na błąd w logice usuwania duplikatów albo na nowe źródło danych, które nie zostało oczyszczone przed połączeniem z głównym zbiorem danych.
assert df['order_id'].is_unique, \
f'order_id not unique: {df.duplicated(subset=["order_id"]).sum()} duplicates'
print('Uniqueness check passed.')Asercje dotyczące wartości kategorii
W przypadku kolumn o skończonym zbiorze prawidłowych wartości — takich jak region lub category — należy sprawdzić asercją, czy każda wartość należy do dozwolonego zbioru. Pozwala to wykryć nieprawidłowe wartości pojawiające się po migracji systemu lub zmianie sposobu wprowadzania danych w systemie nadrzędnym. Prawidłowe zbiory należy definiować w konfiguracji potoku, aby można je było łatwo aktualizować, gdy firma wejdzie na nowe rynki.
VALID_REGIONS = {'North', 'South', 'East', 'West', 'Central'}
VALID_CATEGORIES = {'electronics', 'apparel', 'home', 'sports', 'beauty', 'other'}
assert df['region'].isin(VALID_REGIONS).all(), \
f'Invalid regions: {df[~df["region"].isin(VALID_REGIONS)]["region"].unique()}'
assert df['category'].isin(VALID_CATEGORIES).all(), \
'Invalid categories found'
print('Categorical checks passed.')Asercje dotyczące zakresu dat
Należy sprawdzić, czy wszystkie daty mieszczą się w oczekiwanym okresie dla danego zbioru danych. Zamówienie z datą w przyszłości jest niemożliwe, a zamówienie datowane przed założeniem firmy wskazuje na uszkodzony rekord. W konfiguracji należy zdefiniować MIN_DATE i MAX_DATE, a następnie sprawdzić asercją, czy kolumna mieści się w tych granicach. Pozwala to również wykrywać daty odpowiadające zerowej epoce Unix (1970-01-01), wynikające z nieprawidłowej konwersji znaczników czasu.
MIN_DATE = pd.Timestamp('2020-01-01')
MAX_DATE = pd.Timestamp('today')
assert (df['order_date'] >= MIN_DATE).all(), 'Date before minimum found'
assert (df['order_date'] <= MAX_DATE).all(), 'Future date found'
print(f'Date range: {df["order_date"].min()} to {df["order_date"].max()}')Kontrola liczby wierszy
Nagła zmiana liczby wierszy względem poprzedniego uruchomienia potoku jest silnym sygnałem problemu w systemie nadrzędnym. Liczbę wierszy z poprzedniego uruchomienia należy zapisać w pliku konfiguracyjnym i sprawdzić asercją, czy nowa liczba mieści się w przedziale tolerancji — na przykład w granicach ±20% względem wartości historycznej. Zbiór danych, który między uruchomieniami traci 50% wierszy, niemal na pewno wskazuje na uszkodzony eksport danych.
EXPECTED_MIN_ROWS = 5000
EXPECTED_MAX_ROWS = 200000
assert EXPECTED_MIN_ROWS <= len(df) <= EXPECTED_MAX_ROWS, \
f'Row count {len(df)} outside expected range [{EXPECTED_MIN_ROWS}, {EXPECTED_MAX_ROWS}]'
print(f'Row count check passed: {len(df)} rows')Grupowanie kontroli w funkcji validate
Wszystkie asercje należy zebrać w jednej funkcji validate(df), którą można wywołać na początku każdego etapu potoku. Każda kontrola w przypadku niepowodzenia zgłasza AssertionError z opisowym komunikatem. Ten wzorzec sprawia, że potok sam dokumentuje swoje działanie: funkcja walidacyjna jest czytelnym maszynowo kontraktem schematu dla DataFrame na danym etapie.
def validate_sales_df(df):
assert not (REQUIRED_COLUMNS - set(df.columns)), 'Missing columns'
assert df['order_id'].is_unique, 'Duplicate order IDs'
assert (df['revenue'] >= 0).all(), 'Negative revenue'
assert df['region'].isin(VALID_REGIONS).all(), 'Invalid region'
print(f'Validation passed: {len(df)} rows, {len(df.columns)} columns')
validate_sales_df(df)Eleganckie rejestrowanie błędów walidacji
W potokach produkcyjnych gwałtowne przerwanie działania przez assert jest akceptowalne podczas programowania, ale niepożądane w zadaniu uruchamianym według harmonogramu. Należy zastąpić bezpośrednie asercje blokami try/except AssertionError, które rejestrują komunikat błędu i opcjonalnie wysyłają alert przed zakończeniem działania. Dzięki temu system monitorowania może przechwycić przyczynę niepowodzenia, a nie tylko ślad stosu nieobsłużonego wyjątku.
import logging
logging.basicConfig(level=logging.INFO)
def validate_with_logging(df):
checks = [
(lambda d: d['order_id'].is_unique, 'Duplicate order IDs'),
(lambda d: (d['revenue'] >= 0).all(), 'Negative revenue found'),
]
for check_fn, msg in checks:
try:
assert check_fn(df), msg
except AssertionError as e:
logging.error(f'VALIDATION FAILED: {e}')
raise
validate_with_logging(df)
print('All checks passed.')Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat koncepcji analizy danych omówionych w tej lekcji.
Podsumowanie lekcji
W tej lekcji nauczyłeś się: sprawdzać wymagane kolumny, dtypes, ograniczenia dotyczące wartości null i poprawność zakresów, weryfikować unikalne klucze, wartości kategorii i zakresy dat oraz grupować wszystkie kontrole w wielokrotnie używanej funkcji validate() z rejestrowaniem zdarzeń. Następnie omówimy niestandardowe agregacje z użyciem apply() dla kolumn i wierszy.
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 „Walidacja schematu i asercje” jest bezpłatna?
Tak — pełny tekst „Walidacja schematu i asercje” 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 „Walidacja schematu i asercje”?
Pisz asercje sprawdzające zakresy kolumn, ograniczenia wartości niepustych i unikatowe klucze, uruchamiane na początku każdego potoku. Ć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 „Walidacja schematu i asercje”?
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 i usuwanie duplikatów
- Wykrywanie i obsługa wartości odstających
- Ujednolicanie niespójnych kategorii
- Walidacja schematu i asercje