Pandas & NumPy Academy · Les

Project instellen en gegevens inlezen

Definieer de projectdoelen, laad gegevens uit een CSV-bestand en een SQLite-database, voeg de bronnen samen en voer een volledige audit van de gecombineerde dataset uit.

Les 1 van 413 stappen

Project instellen en gegevens inlezen is een gratis Pandas & NumPy Academy-les op CoddyKit. Dit is les 1 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Pandas & NumPy Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Doel van het eindproject

In dit eindproject breng je alle vaardigheden uit de cursus samen — NumPy, Pandas, visualisatie, statistische toetsen, databaseconnectiviteit en pijplijnontwerp — in één end-to-end-werkstroom. Het project simuleert een echte taak van een analist: ruwe gegevens uit twee bronnen inlezen (een CSV-bestand en een databasetabel), deze samenvoegen, de gegevenskwaliteit controleren, geavanceerde KPI's berekenen, trends visualiseren en een verzorgd rapport exporteren. Dit weerspiegelt wat professionele data-analisten dagelijks in de praktijk doen.

Projectdoelen en KPI's definiëren

Definieer voordat je ook maar één regel code schrijft je projectdoelen en de Key Performance Indicators (KPI's) die je gaat berekenen. Leg vast: Welke zakelijke vraag beantwoord je? Over welke gegevensbronnen beschik je? Welke uitvoerformaten zijn nodig? Voor dit eindproject geldt: Analyseer maandelijkse omzettrends per productcategorie, bereken klantbehoud per cohort, identificeer de beste regio's op basis van winstmarge en exporteer een rapport met visualisaties. Een duidelijk doel voorkomt scope-uitbreiding en houdt de pijplijn gericht.

# 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')

Gegevens uit CSV laden

Laad de CSV met expliciete argumenten voor dtype en parse_dates om fouten bij het afleiden van typen te voorkomen. In een echt project kan de CSV door een ander systeem met andere conventies zijn geëxporteerd — stel indien nodig encoding, sep en thousands in. Controleer onmiddellijk shape, dtypes en head() om te bevestigen dat het laden correct is verlopen voordat je gegevens transformeert. Deze eerste inspectie brengt vaak problemen met tekencodering, extra koprijen of onverwachte kolomnamen aan het licht.

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))

Gegevens uit de database laden

De tweede gegevensbron is de klantentabel in een SQLite-database. Laad met een SQL SELECT alleen de kolommen die nodig zijn voor de analyse, in plaats van de hele tabel te laden. Voeg de twee bronnen samen op customer_id om elke bestelling aan te vullen met klantdemografische gegevens. Controleer vóór het samenvoegen of de sleutels customer_id in beide bronnen hetzelfde type hebben — een veelvoorkomende oorzaak van stil mislukte samenvoegingen is het vergelijken van een sleutel van het type int32 met een sleutel van het type string.

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))

De twee bronnen samenvoegen

Voeg bestellingen en klanten samen op customer_id met een left join, zodat alle bestellingen behouden blijven, ook als een klantrecord ontbreekt. Controleer na het samenvoegen hoeveel bestellingen geen overeenkomende klant hebben (customer_name.isna().sum()) — dit is een signaal voor de gegevenskwaliteit dat nader onderzoek verdient. Bekijk de vorm van het resulterende DataFrame om te bevestigen dat de samenvoeging geen onverwachte rijen heeft gedupliceerd of verwijderd. Documenteer de logica van de samenvoeging in een opmerking voor toekomstige beheerders.

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%})')

Volledige checklist voor gegevenscontrole

Voer na het laden en samenvoegen een systematische gegevenscontrole uit voordat je analyseert. Controleer: het totale aantal rijen en kolommen, ontbrekende waarden per kolom (percentage), de typen van alle kolommen, dubbele bestel-ID's, de dekking van het datumbereik, negatieve waarden in numerieke kolommen en de kardinaliteit van categorische kolommen. Documenteer de bevindingen in een tekstsamenvatting. Door problemen met de gegevenskwaliteit hier op te sporen, voorkom je stille fouten in latere KPI-berekeningen.

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')

Afwijkingen in datumparsing herstellen

Datumkolommen uit CSV-exporten bevatten vaak uitzonderingen: toekomstige datums die niet kunnen bestaan, datums uit het verkeerde jaar (een veelvoorkomende invoerfout) of ontbrekende datums voor geannuleerde bestellingen. Valideer na het parsen van datums het verwachte bereik en vervang waarden buiten dat bereik door NaT. Controleer ook bestellingen waarvoor order_date < customer signup_date geldt — onmogelijke gebeurtenissen die wijzen op problemen met de gegevenskwaliteit en die je in het controlerapport moet markeren.

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

Negatieve aantallen en retouren verwerken

Negatieve aantallen in een besteltabel staan meestal voor retouren of terugbetalingen. Verwijder ze niet zomaar, maar splits ze op in twee DataFrames: positieve bestellingen en retouren. Zo kun je de bruto-omzet (alleen positieve bestellingen) en netto-omzet (positieve + negatieve waarden) afzonderlijk berekenen, wat een nauwkeuriger beeld van de onderneming geeft. Voeg aan elke rij een booleaanse kolom is_return toe en bewaar beide in het samengevoegde DataFrame voor controledoeleinden.

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)
)

Volledigheid van de koppeling controleren

Controleer na een left join of de koppeling volledig is zoals verwacht. Tel hoeveel unieke waarden van customer_id in de bestellingen voorkomen maar niet in de klantentabel. Dit zijn weesrecords — klanten die bestellingen hebben geplaatst maar geen klantrecord hebben. Ze kunnen verwijderde accounts, afrekenen als gast of een ontbrekende stap in de datapijplijn vertegenwoordigen. Documenteer het aantal en beslis of je ze uitsluit van de analyse van klantbehoud, maar wel meetelt in de omzettotalen.

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}')

De gecontroleerde dataset opslaan

Sla de opgeschoonde en samengevoegde dataset na de controle op als Parquet, zodat volgende stappen in de pijplijn (feature-engineering, KPI-berekening, visualisatie) deze direct opnieuw kunnen laden zonder de samenvoeg- en parsebewerkingen te herhalen. Schrijf afzonderlijke bestanden voor de schone bestellingen en het DataFrame met retouren. Dankzij dit controlepuntpatroon kan de pijplijn worden hervat en kun je latere stappen debuggen zonder het inlezen opnieuw uit te voeren.

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)}')

Samenvattend controlerapport

De laatste stap van gegevensinname is het schrijven van een kort auditoverzicht waarin je vastlegt wat je hebt gevonden. Dit kan een afgedrukt logboek of een markdownbestand zijn. Neem het volgende op: het aantal rijen dat uit elke bron is geladen, het matchpercentage bij het samenvoegen, het datumbereik, het percentage ontbrekende waarden, het aantal gevonden retouren en eventuele afwijkingen. Het auditoverzicht wordt onderdeel van het uiteindelijke resultaat en helpt belanghebbenden erop te vertrouwen dat de gegevens vóór de analyse goed zijn opgeschoond.

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.')

Korte controle

Test je begrip van de concepten voor gegevensanalyse uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat doelen en configuratie vooraf definiëren de pipeline gericht en onderhoudbaar houdt, dat expliciete dtype- en parse_dates-argumenten in read_csv stille typefouten voorkomen en dat een systematische checklist voor gegevensaudits (duplicaten, ontbrekende waarden, onmogelijke datums, negatieve aantallen) kwaliteitsproblemen opspoort voordat die KPI-berekeningen verstoren. Hierna schonen we de gegevens op en maken we kenmerken voor de analyse.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Project instellen en gegevens inlezen” gratis?

Ja — de volledige tekst van “Project instellen en gegevens inlezen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Pandas & NumPy Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Wat leer ik in “Project instellen en gegevens inlezen”?

Definieer de projectdoelen, laad gegevens uit een CSV-bestand en een SQLite-database, voeg de bronnen samen en voer een volledige audit van de gecombineerde dataset uit. Je oefent met Pandas & NumPy Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Pandas & NumPy Academy te beginnen?

Ervaring vooraf is niet nodig. Pandas & NumPy Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.

Hoe lang duurt de les “Project instellen en gegevens inlezen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Pandas & NumPy Academy?

Ja. Elke les over Pandas & NumPy Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Project instellen en gegevens inlezen
  2. Gegevens opschonen en features construeren
  3. Analyse en KPI-berekening
  4. Definitieve visualisatie en export van het rapport
← Terug naar Pandas & NumPy Academy