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.NaTObsł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
- Konfiguracja projektu i wczytywanie danych
- Czyszczenie danych i inżynieria cech
- Analiza i obliczanie KPI
- Końcowa wizualizacja i eksport raportu