Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hoofdstuk 13 — Introductie tot pandas: Series en DataFrame

Let op: De tekst is in het Nederlands; alle Python codevoorbeelden zijn in het Engels.

Doel van dit hoofdstuk:

  • Begrijpen wat pandas is en wanneer je het gebruikt ten opzichte van puur Python of NumPy.
  • Kennismaken met de twee kernobjecten: Series en DataFrame.
  • Leren hoe je tabulaire data maakt, inspecteert, selecteert en bewerkt.
  • Inzicht krijgen in indexen, uitlijning (alignment), dtypes en omgaan met missende waarden op basisniveau.

Aanbevolen voorkennis: Python‑basis, NumPy‑arrays (Hoofdstuk 6–11).

13.1 Wat is pandas en waarom?

pandas is een bibliotheek voor data‑analyse in Python, geoptimaliseerd voor gestructureerde (tabelvormige) data. Het biedt:

  • Series (1D gelabelde array) en DataFrame (2D tabel met rijen en kolommen).
  • Krachtige indexering, selectie, groepering, reshaping en I/O (CSV, Excel, Parquet, SQL).
  • Vectorized operations met automatische uitlijning op labels (indexen).

Installatie (indien nodig):

pip install pandas

Basisimport:

import pandas as pd
import numpy as np

13.2 Series: een gelabelde 1D‑array

Een Series is vergelijkbaar met een 1D NumPy‑array, maar met labels (index) en rijkere functionaliteit.

13.2.1 Series maken

import pandas as pd

s = pd.Series([10, 20, 30], index=["a", "b", "c"], name="scores")
print(s)
# a    10
# b    20
# c    30
# Name: scores, dtype: int64

Belangrijke attributen: s.index, s.values, s.dtype, s.name.

Je kunt ook vanuit een dict maken (keys worden index):

data = {"apples": 3, "bananas": 5, "oranges": 2}
stock = pd.Series(data)

13.2.2 Selectie en slicing

s["a"]          # label-based; returns scalar 10
s[["a", "c"]]  # fancy indexing -> Series
s[0]             # position-based; discouraged, gebruik .iloc

s.loc["a"]      # label-based expliciet
s.iloc[0]        # position-based expliciet

s["a":"c"]     # label-slice inclusief eindlabel
s.iloc[0:2]      # position-slice exclusief einde (zoals Python/NumPy)

13.2.3 Vectorbewerkingen en uitlijning

Operaties zijn elementgewijs en worden uitgelijnd op labels.

s1 = pd.Series([1, 2, 3], index=["a", "b", "c"])
s2 = pd.Series([10, 20, 30], index=["b", "c", "d"])

s1 + s2
# a     NaN
# b    11.0
# c    23.0
# d     NaN
# dtype: float64

Missende combinaties geven NaN. Gebruik fill_value met method chaining via .add e.d.:

(s1.add(s2, fill_value=0))
# a     1.0
# b    12.0
# c    33.0
# d    30.0

13.2.4 Basisstatistiek en methodes

s.mean(), s.median(), s.std()
s.min(), s.max()
s.isna(), s.notna()
s.fillna(0)
s.astype("float32")

13.3 DataFrame: een 2D tabel

Een DataFrame is een verzameling Series die kolommen vormen, met een gedeelde rij‑index.

13.3.1 DataFrame maken

Constructors vanuit dict, lijst van dicts, NumPy, of CSV/Parquet/…

import numpy as np

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Charlie"],
    "age": [25, 32, 29],
    "score": [88.5, 92.0, 79.0],
})

# Met aangepaste index
people = pd.DataFrame(
    [[25, 88.5], [32, 92.0], [29, 79.0]],
    index=["Alice", "Bob", "Charlie"],
    columns=["age", "score"],
)

Veelgebruikte attributes en inspectie:

df.shape, df.dtypes, df.index, df.columns

df.head()   # eerste 5 rijen
df.tail(3)  # laatste 3 rijen
df.info()   # kolomtypes, non-null counts
df.describe()  # numerieke samenvatting

13.3.2 Selectie: kolommen en rijen

# Kolommen
ages = df["age"]         # Series
subset = df[["name", "score"]]  # DataFrame

# Rijen
first_row = df.iloc[0]          # Series (row)
rows_1_3 = df.iloc[1:3]         # DataFrame slice
row_bob = people.loc["Bob"]    # via indexlabel

# Rijen + kolommen (2D selectie)
val = df.loc[0, "score"]       # scalar
block = df.loc[0:1, ["name", "score"]]

Regels:

  • Gebruik .loc[rows, cols] voor labelgebaseerd, .iloc[rows, cols] voor positiegebaseerd.
  • Enkelvoudige kolomselectie df["col"] geeft een Series; dubbele haken df[["c1", "c2"]] geeft een DataFrame.

13.3.3 Filteren en booleaanse indexering

mask = (df["age"] >= 30) & (df["score"] > 90)
df[mask]

# Met loc, explicieter en uitbreidbaar
df.loc[(df["age"] >= 30) & (df["score"] > 90), ["name", "score"]]

13.3.4 Nieuwe kolommen en vectorbewerkingen

df["passed"] = df["score"] >= 85

# Vectorbewerkingen uitgelijnd op index
df["score_norm"] = (df["score"] - df["score"].mean()) / df["score"].std()

# Met NumPy ufuncs
df["age_log"] = np.log(df["age"])  # werkt elementgewijs

13.3.5 Dtypes en conversies

df.dtypes

# Conversie
df["age"] = df["age"].astype("int16")
df = df.astype({"score": "float32"})

# Categoricals
cats = pd.Series(["low", "med", "high"]).astype("category")

13.3.6 Missende waarden (NaN) basis

df2 = pd.DataFrame({"a": [1, np.nan, 3], "b": [np.nan, 5, 6]})

df2.isna()           # booleaanse DataFrame
df2.dropna()         # rijen met NaN weg

df2.fillna({"a": 0, "b": df2["b"].mean()})  # per kolom vulling

13.3.7 Sorteren en herindexeren

df.sort_values(by=["score", "age"], ascending=[False, True])
df.sort_index()  # sorteer op rijindex

# Herindexeren
df_re = df.reindex([0, 1, 2, 3])  # voegt evt. NaN toe voor ontbrekende rijen

13.4 Indexfilosofie en uitlijning

  • Indexen labelen rijen/kolommen en sturen selectie, join/merge, en alignment.
  • Operaties tussen Series/DataFrames lijnen uit op indexlabels; ontbrekende labels → NaN.
  • Reset/zet index waar nuttig:
df_reset = people.reset_index(names="person")
df_set = df_reset.set_index("person")

13.5 In‑/uitvoer (teaser)

Uitgebreide I/O volgt in Hoofdstuk 14. Kort voorbeeld:

# CSV lezen en schrijven
df = pd.read_csv("data.csv")
df.to_csv("out.csv", index=False)

# Parquet (vereist pyarrow of fastparquet)
# df.to_parquet("out.parquet")

13.6 Veelvoorkomende valkuilen en tips

  • Gebruik .loc en .iloc i.p.v. df[row][col] (dat maakt onnodige kopieën en kan SettingWithCopyWarnings geven).
  • Let op automatische uitlijning; het is vaak gewenst, maar kan tot NaN leiden als labels niet overeenkomen.
  • Werk zoveel mogelijk kolomgewijs (vectorized) in plaats van rij‑loops voor performance en duidelijkheid.
  • Gebruik df.info() en df.dtypes vroeg om types en missende waarden te begrijpen.

13.7 Samenvatting

Je leerde de basis van pandas met Series en DataFrame: maken, selecteren, filteren, berekenen, en omgaan met missende waarden. In de volgende hoofdstukken duiken we in I/O (CSV/Excel/Parquet/SQL), wrangling en groeperen/pivoteren.