Python Pandas Tutorial: Complete Gids voor Data Manipulatie
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
Inhoudsopgave
- Wat is Pandas en waarom gebruiken?
- Pandas installatie en import
- DataFrame basis: Creëren en bekijken
- Data inlezen en exporteren
- Data exploratie en statistieken
- Data cleaning en preprocessing
- Data manipulatie: Filteren, sorteren, groeperen
- Data samenvoegen: Merge en Join
- Werken met tijdreeksen
- Praktijkvoorbeeld: E-commerce data analyse
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 JOINleft
Alle rijen van links + matching rechts
SQL: LEFT JOINright
Alle rijen van rechts + matching links
SQL: RIGHT JOINouter
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