Ga naar hoofdinhoud

Exploratory Data Analysis van Craft Beers: Data Profiling

In deze tutorial leer je over exploratory data analysis (EDA) in Python, en specifieker, data profiling met pandas.
Bijgewerkt 2 okt 2026  · 14 min lezen

Verken met AI

ChatGPTClaudePerplexity

Redactionele noot: Jean-Nicholas Hould is data scientist bij Intel Security in Montreal en hij leert op zijn blog hoe je start met data science.

Exploratory data analysis (EDA) is een statistische aanpak die erop gericht is een dataset te ontdekken en samen te vatten. In deze stap van het data-scienceproces wil je de structuur van je dataset, de variabelen en hun onderlinge relaties verkennen.

In dit artikel focus je op één aspect van exploratory data analysis: data profiling.

Data profiling draait om het samenvatten van je dataset via beschrijvende statistieken. Je wilt een scala aan metingen gebruiken om je dataset beter te begrijpen. Datatypen, missende waarden, gemiddelde, mediaan en standaarddeviatie zijn slechts enkele van de vele elementen die je nodig hebt bij het profileren van een dataset. Het doel van data profiling is om een solide begrip van je data te krijgen, zodat je daarna je data op verschillende manieren kunt bevragen en visualiseren.

Weet waar je data vandaan komt

Voordat je aan EDA begint, moet je zoveel mogelijk weten over de herkomst van de data die je analyseert. Je moet begrijpen hoe de data is verzameld en hoe deze is verwerkt. Zijn er eerdere transformaties op de data uitgevoerd die je analyse kunnen beïnvloeden?

Je moet deze vragen over je dataset kunnen beantwoorden:

  • Hoe is de data verzameld?
  • Is het een steekproef?
  • Is er correct bemonsterd?
  • Is de dataset op enigerlei wijze getransformeerd?
  • Zijn er bekende problemen met de dataset?

Als je niet begrijpt waar de data vandaan komt, wordt het lastig om betekenisvolle conclusies uit de dataset te trekken. Je loopt ook het risico om zeer belangrijke analysemissers te begaan.

Daarnaast moet je ervoor zorgen dat de dataset op een gestandaardiseerde manier is gestructureerd. Het aanbevolen formaat is de derde normale vorm, ook wel tidy data genoemd. Een “tidy” dataset heeft de volgende kenmerken:

  • Elke variabele vormt een kolom en bevat waarden
  • Elke observatie vormt een rij
  • Elk type observationele eenheid vormt een tabel

Door dit gestandaardiseerde formaat te respecteren, gaat je analyse sneller, omdat het compatibel is met veel tools en libraries.

Data Profiling

In dit artikel gebruik je een dataset met Craft Beers van de CraftCans-website. Deze dataset bevat alleen gegevens over bier in blik van brouwerijen in de Verenigde Staten. Het is op de website niet duidelijk of deze dataset elk bier in blik in de VS bevat of niet. Om veilig te zijn, beschouw je deze dataset als een steekproef die vooroordelen kan bevatten.

Dit is de structuur van de datasets die je gebruikt:

Bieren:

  • ID: Unieke identifier van het bier.
  • Name: Naam van het bier.
  • ABV: Alcoholpercentage (alcohol by volume) van het bier.
  • IBU: International Bittering Units van het bier.
  • Style: Stijl van het bier.
  • Ounces: Aantal ounces bier.

Brouwerijen:

  • ID: Unieke identifier van de brouwerij.
  • Name: Naam van de brouwerij.
  • City: Stad waar de brouwerij is gevestigd.
  • State: Staat waar de brouwerij is gevestigd.

Datatypen

De eerste stap is het begrijpen van de samenstelling van je dataset.

Met welke variabelen heb je te maken?

Meestal kun je de data in een van deze categorieën indelen:

  • Numeriek
  • Categorisch
  • Tekst
  • Datum

Je importeert eerst de datasets die je in deze repository vindt met de from_csv-functie van pandas. Je voegt ook de datasets beers en breweries samen om de analyse later te vergemakkelijken.

import pandas as pd

beers = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_beers.csv")
breweries = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_breweries.csv")

beers_and_breweries = pd.merge(beers, 
                               breweries, 
                               how='inner', 
                               left_on="brewery_id", 
                               right_on="id", 
                               sort=True,
                               suffixes=('_beer', '_brewery'))

Met de pandas-bibliotheek kun je de functie dtypes uitvoeren om elke kolom en het datatype ervan te tonen.

beers.dtypes

Dat levert je het volgende resultaat op:

abv           float64
ibu           float64
id              int64
name           object
style          object
brewery_id      int64
ounces        float64
dtype: object

Zoals je hierboven ziet, groepeert die functie de verschillende datatypen niet netjes. De diverse numerieke datatypen (float64 en int64) worden niet samengenomen in één categorie zoals we zouden willen. Ook worden sommige kolommen als objecten vermeld, wat niet erg behulpzaam is.

Om dit te omzeilen kun je je eigen functie bouwen die de categorie van elke kolom in een DataFrame bepaalt.

def get_var_category(series):
    unique_count = series.nunique(dropna=False)
    total_count = len(series)
    if pd.api.types.is_numeric_dtype(series):
        return 'Numerical'
    elif pd.api.types.is_datetime64_dtype(series):
        return 'Date'
    elif unique_count==total_count:
        return 'Text (Unique)'
    else:
        return 'Categorical'

def print_categories(df):
    for column_name in df.columns:
        print(column_name, ": ", get_var_category(df[column_name]))

Beers-variabelen

print_categories(beers)

Het bovenstaande commando geeft je het volgende resultaat terug:

abv :  Numerical
ibu :  Numerical
id :  Numerical
name :  Categorical
style :  Categorical
brewery_id :  Numerical
ounces :  Numerical

Breweries-variabelen

print_categories(breweries)

Dat levert je het volgende resultaat op:

name :  Categorical
city :  Categorical
state :  Categorical
id :  Numerical

Met deze informatie kun je onze dataset al beter begrijpen. Je weet dat je alleen met categorische en numerieke data te maken hebt. Numerieke variabelen kun je gebruiken om allerlei metingen te extraheren, zoals het gemiddelde, de standaarddeviatie, enzovoort. Categorische variabelen zijn doorgaans een interessante manier om de data te segmenteren en te groeperen. Je zou bijvoorbeeld willen begrijpen hoe de IBU verschilt tussen de verschillende bierstijlen.

Beschrijvende statistieken

In deze sectie loop je door verschillende beschrijvende statistieken die je kunt gebruiken om onze data beter te begrijpen. Je zult merken dat elk van deze metingen op zichzelf niet heel behulpzaam is. De combinatie van deze verschillende metingen levert de meeste waarde op.

Je richt je op de variabele IBU omdat dit een numerieke variabele is. Dit type variabele biedt een breder scala aan metingen dan categorische variabelen. Je kunt nog steeds metingen uitvoeren op je categorische variabelen, maar je bent dan veel beperkter.

Lengte

De functie len telt het aantal observaties in een Series. De functie telt alle observaties, ongeacht of er missende of null-waarden zijn.

length = len(beers["ibu"])
print(length)

In deze Series hebben we in totaal 2410 observaties.

Aantal

De functie count geeft het aantal niet-NA/niet-null observaties in een Series terug.

count = beers["ibu"].count()
print(count)

Zoals je ziet, heb je 1405 niet-null observaties in de Series.

Missende waarden

Met de Length en de Count kunnen we nu het aantal missende waarden berekenen. Het aantal missende waarden is het verschil tussen de Length en de Count.

number_of_missing_values = length - count
pct_of_missing_values = float(number_of_missing_values / length)
pct_of_missing_values = "{0:.1f}%".format(pct_of_missing_values*100)
print(pct_of_missing_values)

Om de missende waarden als percentage weer te geven, deel je simpelweg het aantal missende waarden door het totale aantal observaties, de lengte. De functie float wordt gebruikt om ervoor te zorgen dat de decimalen in de deling worden meegenomen. De functie format wordt gebruikt om het getal netjes als percentage op te maken.

In dit geval mis je bijna 42% van de variabele IBU. Dit is belangrijk om te weten omdat het je analyse zal beïnvloeden. De meeste beschrijvende statistieken negeren deze missende waarden en dat veroorzaakt zeker een bias.

Minimum/maximumwaarde

De minimum- en maximumwaarde van een dataset kun je eenvoudig verkrijgen met de functies min en max op een Series.

print("Minimum value: ", beers["ibu"].min())
print("Maximum value: ", beers["ibu"].max())

De min/max-waarden helpen om het bereik van waarden in een variabele te begrijpen. In dit geval loopt de IBU van 4 tot 138.

Modus

De modus is de meest voorkomende waarde in een dataset. Je kunt deze verkrijgen met de functie mode op een Series.

print(beers["ibu"].mode())

In een normale verdeling is de modus gelijk aan het mean en de median.

In dit geval is de modus van de variabele IBU 20. Dat is de meest voorkomende IBU in onze dataset.

Gemiddelde

Het gemiddelde is een maat voor centrale tendentie. Het is de som van de waarden gedeeld door het aantal niet-missende observaties.

Je verkrijgt het met de functie mean op een Series.

mean = beers["ibu"].mean()

Het gemiddelde is gevoelig voor uitschieters. Een paar extreme waarden kunnen het gemiddelde sterk veranderen en het omhoog of omlaag trekken.

Mediaan

De mediaan is ook een maat voor centrale tendentie. Het is het getal precies in het midden van een geordende lijst met numerieke waarden.

median = beers["ibu"].median()

Bij scheve verdelingen is de mediaan een veel betere maat voor centrale tendentie dan het gemiddelde.

In het geval van de IBU-verdeling liggen gemiddelde en mediaan in dezelfde ordegrootte.

Standaarddeviatie

De standaarddeviatie is een maat voor spreiding. Een hoge standaarddeviatie geeft aan dat de datapunten verdeeld zijn over een brede range aan waarden. De standaarddeviatie wordt uitgedrukt in dezelfde eenheid als de waarden.

standarddev = beers["ibu"].std()

In dit geval is de standaarddeviatie ~26. Precies 25.954065911259324. Als de verdeling van IBU een normale verdeling zou zijn, dan weet je dat ~68% van de observaties binnen één standaarddeviatie van het gemiddelde ligt.

Kwantielstatistieken

Kwantielen zijn snijpunten die een verdeling in gelijke delen splitsen. Veel kwantielen hebben hun eigen naam. Als je een verdeling in vier gelijke groepen splitst, heet het kwantiel dat je hebt gemaakt een quartile. Je kunt eenvoudig kwantielen maken met de functie quantile op een Series. Je kunt aan die functie een array meegeven met de verschillende te berekenen kwantielen. In het onderstaande geval willen we onze verdeling in vier gelijke groepen splitsen.

quantile = beers["ibu"].quantile([.25, .5, .75])
0.25 21.0
0.50 35.0
0.75 64.0
Name: ibu, dtype: float64

Zoals je hierboven ziet, is het 50%-kwantiel gelijk aan de mediaan. Dat is de waarde die de dataset in tweeën splitst. Je kunt ook opmerken dat 75% van de observaties gelijk is aan of lager dan 64 IBU. Bovendien ligt 50% van de verdeling tussen 21 en 64 IBU. Het is belangrijk om te benadrukken dat de missende waarden in deze statistieken niet worden meegenomen.

Distributieplots

Visualisaties zijn erg nuttig bij exploratory data analysis. In dit artikel gaan we niet dieper in op visualisaties. Toch kunnen we het bij data profiling niet hebben zonder het belang van een frequentieverdelingsplot te noemen. Het is een van de simpelste maar krachtigste visualisaties. Het laat de frequentie van elke waarde in onze dataset zien.

Voor deze visualisatie gebruiken we de seaborn`` library with thedisplotfunction. This function expects aSeries` zonder missende waarden.

import seaborn as sns
sns.set(color_codes=True)
sns.set_palette(sns.color_palette("muted"))

sns.distplot(beers["ibu"].dropna());

distribution plot

In dit distributieplot zie je duidelijk een paar van de waarden die we eerder hebben berekend. De minimale waarde ligt dicht bij 0 IBU en de maximale waarde ligt dicht bij 140 IBU. Je ziet duidelijk dat de meest voorkomende waarde rond de 20 IBU ligt. Naast deze informatie zien we nu een piek rond de 60 IBU.

Waarom zijn er twee pieken in deze verdeling?

Wat kan dit verklaren? Dit is een aspect dat we in de tweede fase van exploratory data analysis kunnen verkennen.

Correlaties

Correlaties zijn een geweldige manier om relaties tussen numerieke variabelen te ontdekken. Er zijn verschillende manieren om de correlatie te berekenen. De Pearson-correlatiecoëfficiënt is een veelgebruikte methode die de lineaire afhankelijkheid tussen twee variabelen meet. De correlatiecoëfficiënt loopt van -1 tot 1. Een correlatie van 1 is een volledig positieve correlatie, een correlatie van -1 is een volledig negatieve correlatie en een correlatie van 0 is een niet-lineaire correlatie. We kunnen die berekening uitvoeren met de functie corr op een Series. Standaard gebruikt deze functie de Pearson-correlatiecoëfficiënt. Het is mogelijk om met deze functie andere berekeningsmethoden te gebruiken.

beers[["abv", "ibu", "ounces"]].corr()
  abv ibu ounces
abv 1 0.670621 0.172529
ibu 0.670621 1 0.054691
ounces 0.172529 0.054691 1

Zoals je hierboven ziet, is de correlatie tussen IBU en zichzelf 1. Uiteraard zijn numerieke variabelen perfect gecorreleerd met zichzelf. Interessanter is dat je ziet dat de correlatie tussen ABV en IBU gelijk is aan 0.670621. Hoewel dit geen volledig positieve correlatie is, is het nog steeds een sterke correlatie. Dit is een interessant aspect dat we later verder kunnen verkennen.

Enkele opmerkingen over niet-numerieke variabelen

De metrics die eerder zijn geëxtraheerd, zijn vooral toepasbaar op numerieke waarden. Als je met andere typen data te maken hebt, zoals categorische data, kun je nog steeds interessante metingen verzamelen. Je zou de frequentie van elke waarde in de dataset kunnen berekenen.

DataFrame heeft een functie genaamd describe die de dataset samenvat. Als je DataFrame alleen categorische of tekstwaarden bevat, wordt de samenvatting specifiek aangepast voor dit datatype.

beers[["name", "style"]].describe()
  name style
count 2410 2405
unique 2305 99
top Nonstop Hef Hop American IPA
freq 12 424

Profiling-bibliotheken

Zoals je hierboven hebt gezien, kan het verzamelen van beschrijvende statistieken een tijdrovend proces zijn. Gelukkig bestaan er bibliotheken die al het rekenwerk voor je doen. Ze leveren een heel duidelijk profiel van je data. pandas-profiling is er daar één van. Die bibliotheek biedt kant-en-klare statistische profilering van je dataset. Omdat de dataset die we gebruiken tidy en gestandaardiseerd is, kunnen we de bibliotheek direct op onze dataset toepassen.

import pandas_profiling 

pandas_profiling.ProfileReport(beers_and_breweries)

Meer vragen

Als je je dataset eenmaal hebt geprofileerd, heb je over het algemeen veel meer vragen dan je in eerste instantie had. Dat is goed, want die nieuwe vragen voeden je exploratory data analysis.

Hier zijn een paar vragen die we tijdens dit profileren hebben verzameld:

  • 41,7% van de IBU-waarden ontbreekt. Hoe komt dat? Hoe kan dat onze analyse beïnvloeden?
  • Er zijn twee pieken in de IBU-verdeling. Wat verklaart dit?
  • Wat verklaart de correlatie tussen IBU en ABV? Wat is de invloed van de bierstijl op deze correlatie?
  • Zijn er verschillen in IBU, ABV of Style tussen geografische regio’s? En hoe zit het met de East Coast versus de West Coast?

Data profiling is geen lineair proces. Terwijl je je dataset filtert en segmenteert, kom je erop terug en verzamel je beschrijvende statistieken over subgroepen van je data.

Vervolgstappen

In dit artikel heb je gezien hoe je een dataset kunt profileren. Je weet nu hoe je variabelen aan specifieke datatyperubrieken toekent. Je hebt ook verschillende beschrijvende statistieken op de dataset berekend en je begrijpt hoe je die metingen interpreteert. Tot slot heb je gezien dat er bibliotheken zijn die je kunnen helpen met het rekenwerk om je dataset te profileren. Nog belangrijker: je hebt meer vragen gegenereerd dan ooit om je exploratory data analysis te voeden.

Bekijk DataCamps Python Exploratory Data Analysis Tutorial.

Onderwerpen
Data-analyse
Data Science
Python

Leer meer over Python

Cursus

Bayesian Data Analysis in Python

4 uur
16.2K
Ontdek alle voordelen van Bayesiaanse data-analyse en pas het toe op allerlei echte situaties!
Bekijk detailsRight Arrow
Start Cursus
Meer bekijkenRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer BekijkenMeer Bekijken