DataPartner365

Jouw partner voor datagedreven groei en inzichten

Python Pandas Tutorial: Complete Gids voor Data Manipulatie

Laatst bijgewerkt: 20 december 2025
Leestijd: 18 minuten
Pandas, Python, Data Science, Data Analyse, Data Engineering

Complete beginnersgids voor Pandas. Leer data manipulatie, analyse en visualisatie met praktische voorbeelden voor data engineers en analysts.

Zoek je Data Analysts?

Vind gespecialiseerde Data Analysts en Python developers voor je data projecten

1. Wat is Pandas en waarom gebruiken?

Definitie

Pandas is een open-source Python library voor data manipulatie en analyse. Het biedt hoogwaardige data structuren en tools voor het werken met gestructureerde data (tabellen, tijdreeksen).

DataFrame

2D gelabelde data structuur (zoals Excel spreadsheet)

Series

1D gelabelde array (één kolom van een DataFrame)

Data I/O

Lezen/schrijven van CSV, Excel, SQL, JSON, Parquet

Data Manipulatie

Filteren, sorteren, groeperen, pivot tabellen

Wanneer gebruik je Pandas?

  • Data cleaning: Ontbrekende waarden, duplicaten, outliers
  • Data transformatie: Kolommen aanpassen, nieuwe berekenen
  • Data analyse: Statistieken, correlaties, trends
  • Data voorbereiding: Voor machine learning modellen
  • Rapportage: Samenvattingen, aggregaties, visualisaties
Zonder Pandas Met Pandas Voordeel
Handmatig CSV lezen pd.read_csv() 10x sneller, minder code
Loops voor berekeningen Vectorized operations 100-1000x sneller
Excel voor analyse Pandas + Python Automatisering, schaalbaar
SQL queries schrijven Pandas filtering Flexibeler, minder complex

Team nodig voor data analyse?

Vind ervaren Data Analysts gespecialiseerd in Pandas en data science

2. Pandas installatie en import

Stap 1: Installatie

# Installeer Pandas met pip
pip install pandas

# Of met conda (voor Anaconda gebruikers)
conda install pandas

# Installeer ook vaak gebruikte dependencies
pip install pandas numpy matplotlib

Stap 2: Import in Python

# Standaard import (gebruikt door 90% van developers)
import pandas as pd
import numpy as np

# Optioneel: veelgebruikte functies direct importeren
from pandas import DataFrame, Series
from pandas import read_csv, read_excel

# Check versie (laatste versie is aanbevolen)
print(pd.__version__)  # Bijv: 2.1.0

Stap 3: Test je installatie

# Maak een eenvoudige DataFrame om te testen
df = pd.DataFrame({
    'Naam': ['Jan', 'Piet', 'Klaas'],
    'Leeftijd': [25, 30, 35],
    'Stad': ['Amsterdam', 'Rotterdam', 'Utrecht']
})

print(df)
print("Pandas werkt correct!")

3. DataFrame basis: Creëren en bekijken

DataFrame creëren

# Methode 1: Van dictionary
data = {
    'Product': ['Laptop', 'Muis', 'Toetsenbord', 'Monitor'],
    'Prijs': [999, 25, 75, 300],
    'Voorraad': [15, 200, 150, 50],
    'Categorie': ['Electronica', 'Accessoires', 'Accessoires', 'Electronica']
}

df = pd.DataFrame(data)
print(df)

Resultaat DataFrame:

Index Product Prijs Voorraad Categorie
0 Laptop 999 15 Electronica
1 Muis 25 200 Accessoires
2 Toetsenbord 75 150 Accessoires
3 Monitor 300 50 Electronica

DataFrame inspecteren

# Basis informatie
print(df.head())          # Eerste 5 rijen
print(df.tail(3))        # Laatste 3 rijen
print(df.shape)           # Dimensies: (rijen, kolommen)
print(df.info())          # Data types en memory usage
print(df.describe())      # Statistieken voor numerieke kolommen

# Kolommen en index
print(df.columns)         # Kolom namen
print(df.index)           # Index range

# Data types per kolom
print(df.dtypes)

Handige inspectie methoden

df.head(n)

Bekijk eerste n rijen (standaard 5)

df.sample(5)

Willekeurige rijen (goed voor grote datasets)

df.nunique()

Aantal unieke waarden per kolom

df.isnull().sum()

Tel ontbrekende waarden per kolom

4. Data inlezen en exporteren

Bestandsformaat Functie Voorbeeld Opties
CSV read_csv() pd.read_csv('data.csv') sep, encoding, header
Excel read_excel() pd.read_excel('data.xlsx') sheet_name, header
JSON read_json() pd.read_json('data.json') orient, lines
Parquet read_parquet() pd.read_parquet('data.parquet') columns, filters
SQL read_sql() pd.read_sql('SELECT * FROM tabel', con) params, index_col

Data inlezen met opties

# CSV inlezen met opties
df = pd.read_csv(
    'sales_data.csv',
    sep=';',                 # scheidingsteken (; ipv ,)
    encoding='utf-8',         # karakter encoding
    header=0,                # rij 0 bevat kolomnamen
    na_values=['NA', 'NULL'], # waarden die als NaN moeten worden gezien
    parse_dates=['Datum'],   # kolommen die datum/tijd zijn
    dtype={                  # data types specificeren
        'ProductID': 'str',
        'Quantity': 'int32'
    }
)

Data exporteren

# Naar CSV
df.to_csv('output.csv', index=False, encoding='utf-8')

# Naar Excel
df.to_excel('output.xlsx', sheet_name='Data', index=False)

# Naar Parquet (efficiënt voor grote datasets)
df.to_parquet('output.parquet', compression='snappy')

# Naar JSON
df.to_json('output.json', orient='records')

# Naar SQL database
df.to_sql('tabel_naam', con=engine, if_exists='replace', index=False)

Klaar voor data analyse projecten?

Vind de juiste experts of plaats je Data Analyst vacature

5. Data exploratie en statistieken

# Basis statistieken
print(df.describe())  # Alleen numerieke kolommen
print(df.describe(include='all'))  # Alle kolommen inclusief categorical

# Unieke waarden en frequenties
print(df['Categorie'].unique())          # Unieke categorieën
print(df['Categorie'].value_counts())     # Aantal per categorie
print(df['Categorie'].value_counts(normalize=True))  # Percentages

# Correlatie matrix
correlatie = df.corr()  # Alleen numerieke kolommen
print(correlatie)

# Samenvatting per groep
print(df.groupby('Categorie')['Prijs'].mean())    # Gemiddelde prijs per categorie
print(df.groupby('Categorie')['Voorraad'].sum())  # Totale voorraad per categorie

# Cross tabulation
print(pd.crosstab(df['Categorie'], df['Voorraad'] > 100))

Geavanceerde statistieken

import pandas as pd
import numpy as np

# Maak een sample dataset
np.random.seed(42)
data = {
    'Sales': np.random.normal(1000, 200, 100),
    'Profit': np.random.normal(200, 50, 100),
    'Region': np.random.choice(['North', 'South', 'East', 'West'], 100),
    'Product': np.random.choice(['A', 'B', 'C'], 100)
}
df = pd.DataFrame(data)

# Uitgebreide statistieken
stats = df.agg({
    'Sales': ['mean', 'median', 'std', 'min', 'max', 'skew', 'kurt'],
    'Profit': ['mean', 'sum', 'count']
})

# Percentielen
percentiles = df['Sales'].quantile([0.25, 0.5, 0.75, 0.9, 0.95])

# Rolling statistics (bewegend gemiddelde)
df['Sales_MA7'] = df['Sales'].rolling(window=7).mean()
df['Sales_Std7'] = df['Sales'].rolling(window=7).std()

print(stats)
print("\nPercentielen:", percentiles)

6. Data cleaning en preprocessing

Ontbrekende waarden

# Check ontbrekende waarden
print(df.isnull().sum())        # Totaal per kolom
print(df.isnull().sum().sum())  # Totaal in hele DataFrame

# Ontbrekende waarden behandelen
# Methode 1: Verwijderen
df_dropped = df.dropna()                    # Verwijder rijen met ANY NaN
df_dropped_cols = df.dropna(axis=1)         # Verwijder kolommen met ANY NaN
df_dropped_thresh = df.dropna(thresh=0.8*len(df))  # Houd rijen met ≥80% data

# Methode 2: Vervangen
df_filled = df.fillna(0)                    # Vervang alle NaN met 0
df_filled_mean = df.fillna(df.mean())       # Vervang met gemiddelde
df_filled_ffill = df.fillna(method='ffill')  # Forward fill
df_filled_bfill = df.fillna(method='bfill')  # Backward fill

# Specifiek per kolom
df['Sales'] = df['Sales'].fillna(df['Sales'].median())
df['Region'] = df['Region'].fillna('Unknown')

Duplicaten verwijderen

# Check duplicaten
print(df.duplicated().sum())  # Totaal aantal duplicaten
print(df[df.duplicated()])    # Toon de duplicaten

# Duplicaten verwijderen
df_no_dups = df.drop_duplicates()                     # Alle kolommen
df_no_dups_subset = df.drop_duplicates(subset=['Product', 'Region'])  # Specifieke kolommen
df_keep_last = df.drop_duplicates(keep='last')          # Houd laatste
df_keep_none = df.drop_duplicates(keep=False)         # Verwijder alle duplicaten

Data transformatie

# Datatype conversie
df['Date'] = pd.to_datetime(df['Date'])
df['Category'] = df['Category'].astype('category')
df['Price'] = pd.to_numeric(df['Price'], errors='coerce')

# String operaties
df['Name'] = df['Name'].str.upper()          # Naar hoofdletters
df['Name'] = df['Name'].str.strip()         # Trim whitespace
df['Name'] = df['Name'].str.replace('  ', ' ')  # Dubbele spaties
df['Email_Domain'] = df['Email'].str.split('@').str[1]  # Extract domein

# Outlier detection en behandeling
Q1 = df['Sales'].quantile(0.25)
Q3 = df['Sales'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# Outliers verwijderen
df_no_outliers = df[(df['Sales'] >= lower_bound) & (df['Sales'] <= upper_bound)]

# Outliers cappen
df['Sales_Capped'] = df['Sales'].clip(lower=lower_bound, upper=upper_bound)

7. Data manipulatie: Filteren, sorteren, groeperen

Filteren (SELECT WHERE in SQL)

# Basis filtering
df_electronica = df[df['Categorie'] == 'Electronica']
df_duur = df[df['Prijs'] > 500]
df_voorraad_laag = df[df['Voorraad'] < 100]

# Meerdere voorwaarden
df_filter = df[(df['Categorie'] == 'Electronica') & (df['Prijs'] > 500)]
df_filter = df[(df['Categorie'] == 'Electronica') | (df['Voorraad'] > 100)]

# Filter met isin() (IN in SQL)
categorieen = ['Electronica', 'Accessoires']
df_filter = df[df['Categorie'].isin(categorieen)]

# Filter met string bevat
df_laptop = df[df['Product'].str.contains('Laptop', case=False)]

# Filter met query() (SQL-like syntax)
df_query = df.query('Prijs > 500 and Voorraad < 100')
df_query = df.query('Categorie in ["Electronica", "Accessoires"]')

Sorteren (ORDER BY in SQL)

# Sorteer op één kolom
df_sorted = df.sort_values(by='Prijs')                # Ascending (standaard)
df_sorted_desc = df.sort_values(by='Prijs', ascending=False)  # Descending

# Sorteer op meerdere kolommen
df_sorted_multi = df.sort_values(by=['Categorie', 'Prijs'], ascending=[True, False])

# Sorteer op index
df_sorted_index = df.sort_index(ascending=False)

Groeperen (GROUP BY in SQL)

# Eenvoudige groepering
grouped = df.groupby('Categorie')['Prijs'].mean()
grouped_sum = df.groupby('Categorie')['Voorraad'].sum()

# Meerdere aggregaties
agg_results = df.groupby('Categorie').agg({
    'Prijs': ['mean', 'min', 'max', 'std'],
    'Voorraad': ['sum', 'mean']
})

# Groeperen op meerdere kolommen
multi_group = df.groupby(['Categorie', 'Product'])['Voorraad'].sum().reset_index()

# Transform (bereken per groep maar houd originele vorm)
df['Prijs_Norm_Per_Cat'] = df.groupby('Categorie')['Prijs'].transform(lambda x: (x - x.mean()) / x.std())

# Pivot tabellen
pivot = df.pivot_table(
    values='Prijs',
    index='Categorie',
    columns='Product',
    aggfunc='mean',
    fill_value=0,
    margins=True  # Voeg totalen toe
)

8. Data samenvoegen: Merge en Join

Merge Types (Vergelijkbaar met SQL JOIN)

inner

Alleen matching rijen

SQL: INNER JOIN
left

Alle rijen van links + matching rechts

SQL: LEFT JOIN
right

Alle rijen van rechts + matching links

SQL: RIGHT JOIN
outer

Alle rijen van beide

SQL: FULL OUTER JOIN
# Voorbeeld datasets
df_products = pd.DataFrame({
    'ProductID': [1, 2, 3, 4],
    'ProductNaam': ['Laptop', 'Muis', 'Toetsenbord', 'Monitor'],
    'Categorie': ['Electronica', 'Accessoires', 'Accessoires', 'Electronica']
})

df_sales = pd.DataFrame({
    'SaleID': [101, 102, 103, 104],
    'ProductID': [1, 2, 1, 5],  # ProductID 5 bestaat niet in products
    'Aantal': [2, 5, 1, 3],
    'Datum': ['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04']
})

# Inner join (default)
df_inner = pd.merge(df_sales, df_products, on='ProductID', how='inner')

# Left join
df_left = pd.merge(df_sales, df_products, on='ProductID', how='left')

# Right join
df_right = pd.merge(df_sales, df_products, on='ProductID', how='right')

# Outer join
df_outer = pd.merge(df_sales, df_products, on='ProductID', how='outer')

# Merge met verschillende kolomnamen
df_sales_rename = df_sales.rename(columns={'ProductID': 'ProdID'})
df_merge_diff = pd.merge(df_sales_rename, df_products, left_on='ProdID', right_on='ProductID')

# Concatenate (stapelen van dataframes)
df_extra = pd.DataFrame({
    'ProductID': [5, 6],
    'ProductNaam': ['Tablet', 'Phone'],
    'Categorie': ['Electronica', 'Electronica']
})

df_all_products = pd.concat([df_products, df_extra], ignore_index=True)

# Join met index
df_products_indexed = df_products.set_index('ProductID')
df_join_index = df_sales.join(df_products_indexed, on='ProductID')

9. Werken met tijdreeksen

Datum/tijd parsing en manipulatie

# Datum kolom parsen
df['Datum'] = pd.to_datetime(df['Datum'], format='%Y-%m-%d')

# Extract datum componenten
df['Year'] = df['Datum'].dt.year
df['Month'] = df['Datum'].dt.month
df['Day'] = df['Datum'].dt.day
df['Weekday'] = df['Datum'].dt.day_name()
df['Quarter'] = df['Datum'].dt.quarter
df['Week'] = df['Datum'].dt.isocalendar().week

# Datum berekeningen
df['Days_Since'] = (pd.Timestamp('today') - df['Datum']).dt.days
df['Is_Weekend'] = df['Datum'].dt.weekday >= 5

# Filteren op datum
df_2024 = df[df['Datum'].dt.year == 2024]
df_jan = df[df['Datum'].dt.month == 1]
df_q1 = df[df['Datum'].dt.quarter == 1]
df_last_30_days = df[df['Datum'] > (pd.Timestamp('today') - pd.Timedelta(days=30))]

Tijdreeks analyse

# Resampling (aggregeren over tijd)
# Stel: dagelijkse sales data
df_daily = df.set_index('Datum')

# Naar wekelijkse aggregatie
df_weekly = df_daily.resample('W').agg({
    'Sales': 'sum',
    'Profit': 'mean',
    'Quantity': 'count'
})

# Naar maandelijkse aggregatie
df_monthly = df_daily.resample('M').agg({
    'Sales': 'sum',
    'Profit': 'mean'
}).round(2)

# Rolling windows (bewegende berekeningen)
df_daily['Sales_MA7'] = df_daily['Sales'].rolling(window=7).mean()      # 7-dagen gemiddelde
df_daily['Sales_MA30'] = df_daily['Sales'].rolling(window=30).mean()    # 30-dagen gemiddelde
df_daily['Sales_Std30'] = df_daily['Sales'].rolling(window=30).std()     # 30-dagen std

# Expanding windows (cumulatief)
df_daily['Sales_Cumsum'] = df_daily['Sales'].expanding().sum()
df_daily['Sales_Cummean'] = df_daily['Sales'].expanding().mean()

# Period-over-period vergelijking
df_monthly['Sales_MoM'] = df_monthly['Sales'].pct_change() * 100  # Maand-op-maand %
df_monthly['Sales_YoY'] = df_monthly['Sales'].pct_change(periods=12) * 100  # Jaar-op-jaar %

# Shift (vergelijken met vorige periode)
df_daily['Sales_Lag1'] = df_daily['Sales'].shift(1)  # Vorige dag
df_daily['Sales_Diff'] = df_daily['Sales'] - df_daily['Sales'].shift(1)

10. Praktijkvoorbeeld: E-commerce data analyse

Complete analyse pipeline

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 1. Data inlezen
orders = pd.read_csv('ecommerce_orders.csv', parse_dates=['order_date'])
products = pd.read_csv('products.csv')
customers = pd.read_csv('customers.csv')

# 2. Data cleaning
# Verwijder duplicaten
orders = orders.drop_duplicates()

# Handle missing values
orders['discount'] = orders['discount'].fillna(0)
customers['city'] = customers['city'].fillna('Unknown')

# Verwijder outliers in order_value
Q1 = orders['order_value'].quantile(0.01)
Q3 = orders['order_value'].quantile(0.99)
orders = orders[(orders['order_value'] >= Q1) & (orders['order_value'] <= Q3)]

# 3. Data samenvoegen
# Merge orders met products en customers
df = pd.merge(orders, products, on='product_id', how='left')
df = pd.merge(df, customers, on='customer_id', how='left')

# 4. Nieuwe features berekenen
df['net_revenue'] = df['order_value'] * (1 - df['discount'])
df['profit_margin'] = (df['net_revenue'] - df['cost_price']) / df['net_revenue']
df['order_month'] = df['order_date'].dt.to_period('M')
df['order_day_of_week'] = df['order_date'].dt.day_name()

# 5. Business KPI's berekenen
# Maandelijkse metrics
monthly_kpis = df.groupby('order_month').agg({
    'order_id': 'count',          # Aantal orders
    'net_revenue': 'sum',        # Totale omzet
    'customer_id': 'nunique',   # Unieke klanten
    'profit_margin': 'mean'      # Gemiddelde marge
}).round(2)

monthly_kpis.columns = ['order_count', 'total_revenue', 'unique_customers', 'avg_margin']

# Customer segmentatie
customer_stats = df.groupby('customer_id').agg({
    'order_id': 'count',
    'net_revenue': 'sum',
    'order_date': ['min', 'max']
}).round(2)

customer_stats.columns = ['total_orders', 'total_spent', 'first_order', 'last_order']

# RFM analysis (Recency, Frequency, Monetary)
max_date = df['order_date'].max()
rfm = df.groupby('customer_id').agg({
    'order_date': lambda x: (max_date - x.max()).days,  # Recency
    'order_id': 'count',                                # Frequency
    'net_revenue': 'sum'                                 # Monetary
})

rfm.columns = ['recency', 'frequency', 'monetary']

# Product performance analysis
product_performance = df.groupby(['product_id', 'product_name']).agg({
    'order_id': 'count',          # Aantal verkocht
    'net_revenue': 'sum',        # Totale omzet
    'profit_margin': 'mean',     # Gemiddelde marge
    'quantity': 'sum'            # Totale hoeveelheid
}).round(2)

product_performance = product_performance.sort_values(by='net_revenue', ascending=False)

# 6. Export resultaten
monthly_kpis.to_csv('monthly_kpis.csv')
product_performance.to_excel('product_performance.xlsx')
rfm.to_parquet('rfm_analysis.parquet')

print("Analyse voltooid! Resultaten geëxporteerd.")
print(f"Totaal aantal orders: {len(df):,}")
print(f"Totale omzet: €{df['net_revenue'].sum():,.2f}")
print(f"Gemiddelde order waarde: €{df['net_revenue'].mean():.2f}")

Klaar om Pandas te gebruiken?

Vind gespecialiseerde Data Analysts of plaats je vacature