0Pricing
Pandas & NumPy Academy · Lekcja

Konfiguracja projektu i wczytywanie danych

Zdefiniuj cele projektu, wczytaj dane z pliku CSV i bazy SQLite, połącz źródła oraz przeprowadź pełny audyt połączonego zbioru danych.

Konfiguracja projektu i wczytywanie danych to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 1 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.

Cel projektu końcowego

W tym projekcie końcowym połączą Państwo wszystkie umiejętności z kursu — NumPy, Pandas, wizualizację, testowanie statystyczne, łączenie z bazami danych i projektowanie potoków — w jednym kompletnym przepływie pracy. Projekt symuluje rzeczywiste zadanie analityka: wczytanie surowych danych z dwóch źródeł (pliku CSV i tabeli bazy danych), ich scalenie, kontrolę jakości danych, obliczenie zaawansowanych KPI, wizualizację trendów oraz eksport dopracowanego raportu. Odzwierciedla to codzienną pracę profesjonalnych analityków danych w branży.

Definiowanie celów projektu i KPI

Zanim napiszą Państwo choć jedną linię kodu, należy określić cele projektu oraz obliczane kluczowe wskaźniki efektywności (KPI). Należy udokumentować: Na jakie pytanie biznesowe odpowiada analiza? Jakie źródła danych są dostępne? Jakie formaty wynikowe są wymagane? W tym projekcie końcowym: przeanalizować miesięczne trendy przychodów w kategoriach produktów, obliczyć utrzymanie kohort, wskazać najważniejsze regiony pod względem marży zysku oraz wyeksportować raport z wizualizacjami. Jasno określony cel zapobiega niekontrolowanemu rozszerzaniu zakresu i pomaga zachować koncentrację potoku.

# Project configuration — define goals upfront
CONFIG = {
    'csv_path': 'data/orders_2024.csv',
    'db_url': 'sqlite:///customer_db.sqlite',
    'db_table': 'customers',
    'output_dir': 'output/',
    'report_path': 'output/report.md',
    'analysis_year': 2024,
    'top_n_regions': 5,
    'rolling_window_days': 30
}

print('Project config loaded.')
print('Target KPIs: monthly revenue, cohort retention, top regions by margin')

Wczytywanie danych z pliku CSV

Plik CSV należy wczytać z jawnym określeniem argumentów dtype i parse_dates, aby uniknąć błędów wnioskowania typów. W rzeczywistym projekcie plik CSV mógł zostać wyeksportowany przez inny system, korzystający z odmiennych konwencji — w razie potrzeby należy ustawić encoding, sep i thousands. Bezpośrednio po wczytaniu należy sprawdzić shape, dtypes i head(), aby potwierdzić poprawność danych przed jakimkolwiek przekształceniem. Taka wstępna kontrola często ujawnia problemy z kodowaniem, dodatkowe wiersze nagłówków lub nieoczekiwane nazwy kolumn.

import pandas as pd

df_orders = pd.read_csv(
    'data/orders_2024.csv',
    dtype={
        'order_id': 'int32',
        'customer_id': 'int32',
        'product_id': 'int32',
        'quantity': 'int16',
        'unit_price': 'float32',
        'region': 'category',
        'category': 'category'
    },
    parse_dates=['order_date'],
    encoding='utf-8'
)
print(f'Orders loaded: {df_orders.shape}')
print(df_orders.dtypes)
print(df_orders.head(3))

Wczytywanie danych z bazy danych

Drugim źródłem danych jest tabela klientów w bazie SQLite. Należy wczytać za pomocą zapytania SQL SELECT tylko kolumny potrzebne do analizy, zamiast wczytywać całą tabelę. Połączenie obu źródeł za pomocą customer_id pozwala uzupełnić każde zamówienie o dane demograficzne klienta. Przed scaleniem należy potwierdzić, że klucze customer_id mają ten sam typ w obu źródłach — częstą przyczyną niezauważonych błędów scalania jest porównywanie klucza int32 z kluczem tekstowym.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///customer_db.sqlite')

df_customers = pd.read_sql_query(
    '''
    SELECT customer_id, customer_name, country,
           acquisition_channel, signup_date
    FROM customers
    ''',
    con=engine,
    dtype={'customer_id': 'int32'},
    parse_dates=['signup_date']
)
print(f'Customers loaded: {df_customers.shape}')
print(df_customers.dtypes)
print(df_customers.head(3))

Scalanie dwóch źródeł

Należy scalić zamówienia z klientami za pomocą customer_id, używając złączenia lewostronnego, aby zachować wszystkie zamówienia, nawet jeśli brakuje rekordu klienta. Po scaleniu należy sprawdzić, ile zamówień nie ma pasującego klienta (customer_name.isna().sum()) — jest to sygnał jakości danych, który warto zbadać. Należy sprawdzić rozmiar wynikowej ramki danych, aby potwierdzić, że scalanie nie powieliło ani nie usunęło nieoczekiwanych wierszy. Logikę scalania należy opisać w komentarzu z myślą o przyszłych osobach utrzymujących kod.

import pandas as pd

# Left join: keep all orders, enrich with customer data where available
df = pd.merge(
    df_orders,
    df_customers,
    on='customer_id',
    how='left'
)

print(f'Orders: {len(df_orders)}, Customers: {len(df_customers)}')
print(f'Merged: {df.shape}')
unmatched = df['customer_name'].isna().sum()
print(f'Orders with no matching customer: {unmatched} ({unmatched/len(df):.1%})')

Pełna lista kontrolna audytu danych

Po wczytaniu i scaleniu należy przeprowadzić systematyczny audyt danych przed rozpoczęciem analizy. Należy sprawdzić: łączną liczbę wierszy i kolumn, braki danych w każdej kolumnie (w procentach), typy danych wszystkich kolumn, zduplikowane identyfikatory zamówień, zakres dat, wartości ujemne w kolumnach liczbowych oraz liczność kategorii w kolumnach kategorycznych. Wyniki należy udokumentować w podsumowaniu tekstowym. Wykrycie problemów z jakością danych na tym etapie zapobiega niezauważonym błędom w późniejszych obliczeniach KPI.

import pandas as pd

def audit_dataframe(df, name='DataFrame'):
    print(f'=== Audit: {name} ===')
    print(f'Shape: {df.shape}')
    print(f'Date range: {df["order_date"].min()} to {df["order_date"].max()}')
    print(f'Duplicate order_ids: {df["order_id"].duplicated().sum()}')
    print('Missing values:')
    missing = df.isnull().sum()
    print(missing[missing > 0].to_string())
    print('Negative quantities:', (df['quantity'] < 0).sum())
    print('Negative prices:', (df['unit_price'] < 0).sum())
    print()

audit_dataframe(df, 'Merged Orders + Customers')

Usuwanie anomalii w analizie dat

Kolumny dat pochodzące z eksportów CSV często zawierają przypadki brzegowe: przyszłe daty, które nie powinny występować, daty z niewłaściwego roku (częsty błąd przy wprowadzaniu danych) lub brakujące daty dla anulowanych zamówień. Po przeanalizowaniu dat należy sprawdzić oczekiwany zakres i zastąpić wartości spoza zakresu wartością NaT. Należy także sprawdzić zamówienia, w których order_date < customer signup_date — są to niemożliwe zdarzenia wskazujące na problemy z jakością danych, które warto odnotować w raporcie z audytu.

import pandas as pd
from datetime import datetime

# Flag impossible dates
df['date_valid'] = (
    (df['order_date'] >= '2024-01-01') &
    (df['order_date'] <= datetime.now())
)
print('Invalid order dates:', (~df['date_valid']).sum())

# Flag orders before customer signup
df['signup_date'] = pd.to_datetime(df['signup_date'])
df['date_before_signup'] = df['order_date'] < df['signup_date']
print('Orders before customer signup:', df['date_before_signup'].sum())

# Set invalid dates to NaT
df.loc[~df['date_valid'], 'order_date'] = pd.NaT

Obsługa ujemnych ilości i zwrotów

Ujemne ilości w tabeli zamówień zazwyczaj oznaczają zwroty lub refundacje. Zamiast po prostu je usuwać, należy podzielić je na dwie ramki danych: zamówienia dodatnie i zwroty. Pozwala to osobno obliczać przychód brutto (wyłącznie zamówienia dodatnie) i przychód netto (zamówienia dodatnie i ujemne), zapewniając dokładniejszy obraz działalności. Każdy wiersz należy oznaczyć kolumną logiczną is_return i zachować oba typy w scalonej ramce danych na potrzeby audytu.

import pandas as pd

# Tag returns
df['is_return'] = df['quantity'] < 0

returns = df[df['is_return']]
orders = df[~df['is_return']]

print(f'Normal orders: {len(orders)}')
print(f'Returns/refunds: {len(returns)} ({len(returns)/len(df):.1%})')
print(f'Return rate by category:')
print(
    df.groupby('category')['is_return']
    .mean()
    .sort_values(ascending=False)
    .round(3)
)

Sprawdzanie kompletności złączenia

Po złączeniu lewostronnym należy sprawdzić, czy złączenie przebiegło zgodnie z oczekiwaniami. Należy policzyć, ile unikalnych wartości customer_id występuje w zamówieniach, ale nie ma ich w tabeli klientów. Są to sieroce rekordy — klienci, którzy złożyli zamówienia, lecz nie mają rekordu klienta. Mogą oznaczać usunięte konta, zakupy gościnne lub lukę w potoku danych. Należy udokumentować tę liczbę i zdecydować, czy wykluczyć te rekordy z analizy utrzymania klientów, ale uwzględnić je w sumach przychodów.

import pandas as pd

order_customers = set(df_orders['customer_id'].unique())
customer_ids = set(df_customers['customer_id'].unique())

orphans = order_customers - customer_ids
print(f'Customer IDs in orders not in customer table: {len(orphans)}')
print(f'Coverage: {len(order_customers & customer_ids) / len(order_customers):.1%} of order customers have records')

# Revenue from unmatched customers
orphan_revenue = df[df['customer_id'].isin(orphans)]['unit_price'].sum()
print(f'Revenue from orphan customers: ${orphan_revenue:,.0f}')

Zapisywanie skontrolowanego zbioru danych

Po przeprowadzeniu audytu należy zapisać oczyszczony i scalony zbiór danych w formacie Parquet, aby kolejne etapy potoku (tworzenie cech, obliczanie KPI, wizualizacja) mogły wczytać go natychmiast bez ponownego wykonywania operacji scalania i analizy dat. Należy zapisać osobne pliki dla czystych zamówień i ramki danych zwrotów. Taki punkt kontrolny umożliwia wznowienie potoku i pozwala debugować późniejsze etapy bez ponownego uruchamiania procesu wczytywania danych.

import os
import pandas as pd

OS_DIR = 'output/'
os.makedirs(OS_DIR, exist_ok=True)

# Save clean orders (excluding returns and invalid dates)
clean_orders = df[
    (~df['is_return']) &
    df['order_date'].notna()
].copy()

clean_orders.to_parquet(OS_DIR + 'clean_orders.parquet', index=False)
df[df['is_return']].to_parquet(OS_DIR + 'returns.parquet', index=False)

print(f'Clean orders saved: {len(clean_orders):,} rows')
print(f'Returns saved: {len(df[df["is_return"]]):,} rows')
print(f'Files in {OS_DIR}: {os.listdir(OS_DIR)}')

Raport podsumowujący audyt

Ostatnim etapem pozyskiwania danych jest napisanie krótkiego podsumowania audytu, w którym zapisane zostaną ustalenia. Może to być wydrukowany dziennik lub plik Markdown. Należy uwzględnić: liczbę wczytanych wierszy z każdego źródła, współczynnik dopasowania podczas scalania, zakres dat, odsetek brakujących wartości, liczbę znalezionych zwrotów oraz wszelkie anomalie. Podsumowanie audytu staje się częścią końcowego rezultatu i pomaga interesariuszom zaufać, że dane zostały prawidłowo oczyszczone przed analizą.

import pandas as pd
from datetime import datetime

def write_audit_summary(df, path):
    lines = [
        '# Data Ingestion Audit',
        f'Generated: {datetime.now().strftime("%Y-%m-%d %H:%M")}',
        '',
        f'- Total records after merge: {len(df):,}',
        f'- Clean orders: {(~df["is_return"]).sum():,}',
        f'- Returns: {df["is_return"].sum():,}',
        f'- Date range: {df["order_date"].min().date()} to {df["order_date"].max().date()}',
        f'- Unique customers: {df["customer_id"].nunique():,}',
        f'- Unique categories: {df["category"].nunique()}',
        f'- Missing unit_price: {df["unit_price"].isna().sum()}'
    ]
    with open(path, 'w') as f:
        f.write('\n'.join(lines))

write_audit_summary(df, 'output/audit.md')
print('Audit summary written.')

Szybki test

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

Podsumowanie lekcji

W tej lekcji nauczyłeś się, że: zdefiniowanie celów i konfiguracji z wyprzedzeniem pozwala zachować koncentrację i łatwość utrzymania potoku, jawne określenie argumentów dtype i parse_dates w read_csv zapobiega cichym błędom typów, a systematyczna lista kontrolna audytu danych (duplikaty, brakujące wartości, niemożliwe daty, ujemne ilości) pozwala wykryć problemy z jakością, zanim zniekształcą obliczenia KPI. Następnie oczyścimy dane i przygotujemy cechy na potrzeby analizy.

Często zadawane pytania

Czy lekcja „Konfiguracja projektu i wczytywanie danych” jest bezpłatna?

Tak — pełny tekst „Konfiguracja projektu i wczytywanie danych” 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 „Konfiguracja projektu i wczytywanie danych”?

Zdefiniuj cele projektu, wczytaj dane z pliku CSV i bazy SQLite, połącz źródła oraz przeprowadź pełny audyt połączonego zbioru danych. Ć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 1 z 4.

Ile czasu zajmuje lekcja „Konfiguracja projektu i wczytywanie danych”?

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