In eerdere tutorials heb je geleerd hoe je met pandas gegevens kunt inlezen en bewerken. Een veelvoorkomende taak bij data-analyse is het groeperen van gegevens om daar vervolgens berekeningen op uit te voeren. Denk bijvoorbeeld aan:
De gemiddelde temperatuur per maand berekenen uit dagelijkse metingen
Het totale verkoopbedrag per klant bepalen uit individuele orders
Het aantal orders per product tellen
Dit is waar de groupby functie van pandas om de hoek komt kijken. Met groupby kun je gegevens groeperen op basis van één of meerdere kolommen, om vervolgens per groep berekeningen uit te voeren.
Wat is groupby?
groupby is een functie in pandas die je gebruikt om gegevens te groeperen op basis van gemeenschappelijke waarden. Het werkt eigenlijk net als een draaitabel in Excel: je kiest één of meer kolommen waarop je wilt groeperen, en vervolgens kun je per groep berekeningen uitvoeren zoals het berekenen van gemiddeldes, totalen of het tellen van waarden.
Het grote voordeel van groupby ten opzichte van een draaitabel is dat je veel flexibeler bent in de berekeningen die je kunt uitvoeren. Daarnaast kun je het eenvoudig automatiseren: schrijf één keer de code en je kunt dezelfde analyse blijven uitvoeren op nieuwe gegevens.
In deze tutorial ga je leren hoe je groupby gebruikt om gegevens te groeperen en te analyseren. Je leert:
Hoe je gegevens groepeert op één kolom
Hoe je groepeert op meerdere kolommen
Een aantal berekeningen die je kunt uitvoeren op gegroepeerde gegevens
Voordat je begint
Maak een nieuw project aan, met een nieuwe virtual environment. Installeer daarin ook pandas.
shell
cdprojects
mkdirpandas_groupby&&cdpandas_groupby
python-mvenv.venv
source.venv/bin/activate# .venv\Scripts\activate.bat voor Windows
python-mpipinstallpandas
python-mpipfreeze>requirements.txt
In deze tutorial ga je werken met gegevens over de WOZ-waarde van het CBS. Je kunt een CSV downloaden op deze pagina. Klik op "Onbewerkte dataset" en vervolgens op "Download CSV". Sla het bestand op in je zojuist aangemaakte projectmap. Voor het gemak kun je het hernoemen naar bijvoorbeeld woz.csv.
Alle code en bestanden van dit project zijn ook op Github te bekijken.
Laden en opschonen
Om goed met de data te kunnen werken maak je een functie voor het laden van het CSV-bestand naar een DataFrame. Hierbij zijn twee aandachtspunten. Ten eerste gebruikt CBS in dit geval zeven spaties gevolgd door een punt voor missende waarde. Tijdens het inladen is het handig om dit om te zetten naar echte missende waarden (NaN). Ten tweede is er de kolom Perioden met gegevens als "1947JJ00" en "2006JJ00". Hier is het handig om alleen het jaartal te pakken, en er integers van te maken. Tot slot gebruikt CBS een aantal codes om regio's mee aan te duiden, het is handiger om met de regionamen te werken. De codering is te vinden via de eerdere link, onder het kopje "metadata".
Maak in je project een bestand data.py aan en plaats daarin twee functies: clean_data en load_data. De code vind je op de Github-pagina van dit project.
Plaats in main.py de volgende code om de gegevens in te laden en te inspecteren:
main.py
fromdataimportclean_data,load_dataif__name__=="__main__":# Schoon de data opclean_data()# Laad de datadf=load_data()# Inspecteer de dataprint(df.head())print(df.info())
Elke rij in de DataFrame is een jaar. Stel dat je nu wilt groeperen op decennium, dan kan dit met groupby. Daarvoor maak je eerst wel een nieuwe kolom Decennium aan, dat voor elke rij aangeeft in welk decennium het jaar valt.
De volgende regel in de functie clean_data in data.py zorgt daarvoor:
data.py
defclean_data():# eerdere code# Maak een kolom decenniumdf["decennium"]=df.loc[:,"jaar"]//10*10# Verdere code
De // operator in Python deelt en rondt af naar beneden. Door eerst te delen door 10 en dan weer te vermenigvuldigen met 10, krijg je het begin van het decennium. Bijvoorbeeld:
1923 // 10 = 192
192 * 10 = 1920
Eerste berekeningen
Nu kun je berekeningen per decennium gaan uitvoeren. Om bijvoorbeeld de gemiddelde WOZ-waarde per decennium te berekenen, gebruik je de volgende code, in berekeningen.py:
berekeningen.py
defwoz_per_decennium(df):# Groepeer op decennium en bereken de gemiddelde WOZ-waardeper_decennium=df.groupby("Decennium")["Gemiddelde WOZ-waarde"].mean()print("Gemiddelde WOZ-waarde per decennium:")print(per_decennium)
Importeer de functie in main.py en voer main.py uit met python main.py. Je zult iets zien als:
Feitelijk koppel je twee acties aan elkaar. Eerst maak je de groepering met df.groupby("Decennium")["Gemiddelde WOZ-waarde"]. Hiermee zeg je: maak een groepering per decennium voor de waardes uit de kolom Gemiddelde WOZ-waarde. Maar hier heb je nog niets aan, want je moet nog aangeven hoe je wilt groeperen. Dat doe je met de .mean-methode. Hiermee geef je aan dat je de gemiddelde waarde wilt per decennium. Je zou ook andere methodes kunnen toepassen, zoals sum, min, max of median.
Je kunt een soortgelijke berekening doen, maar dan per regio:
berekeningen.py
defwoz_per_regio(df):# Groepeer op regio en bereken de gemiddelde WOZ-waardeper_regio=(df.groupby("Regio")["Gemiddelde WOZ-waarde"].mean().sort_values().round(2))print("Gemiddelde WOZ-waarde per regio:")print(per_regio)
Je ziet dat je nu niet alleen .mean() toepast op de groupby-functie, maar ook sort_values() en round(2). Hiermee zeg je dat je de gegevens wilt sorteren en wilt afronden op twee decimalen.
De agg-methode
Tot nu toe heb je steeds één berekening per keer uitgevoerd op de gegroepeerde gegevens, bijvoorbeeld alleen het gemiddelde of alleen de mediaan. Maar vaak wil je meerdere berekeningen tegelijk uitvoeren. Daar komt de agg-methode van pas.
De agg-methode (kort voor aggregate) biedt twee voordelen:
Je kunt meerdere berekeningen in één keer uitvoeren
Je kunt zelf de namen van de resultaatkolommen bepalen
Bijvoorbeeld:
berekeningen.py
defwoz_per_regio_agg(df):# Groepereer op regio en bereken de gemiddelde WOZ-waardeper_regio=df.groupby("Regio").agg({"Gemiddelde WOZ-waarde":"mean"})# per_regio is nu een DataFrameper_regio=per_regio.sort_values(by="Gemiddelde WOZ-waarde").round(2)print("Gemiddelde WOZ-waarde per regio:")print(per_regio)
Het resultaat is hetzelfde als de code hiervoor, behalve dat per_regio in het eerste geval een Series oplevert en in het tweede geval een DataFrame.
Lees nog eens Gegevens inlezen en opslaan als je wilt weten hoe het ook alweer zit met Series en DataFrames.
Het volgende voorbeeld maakt duidelijk dat je agg kunt gebruiken als je meerdere berekeningen wilt toepassen op dezelfde kolom. Stel dat je niet alleen het gemiddelde per regio wilt zien, maar ook de mediaan. Dan kan dat met agg:
Je ziet dat je in plaats van een dict met kolom:functie toepast, nu twee parameters opgeeft (gemiddelde en mediaan) met een tuple van een kolomnaam en de te gebruiken functie. Dit is nodig omdat je twee functies op dezelfde kolom wilt toepassen. Dit werkt daarom niet:
Je ziet dat je in plaats van een kolomnaam in groupby meegeeft, je een list met twee kolomnamen meegeeft. De rest blijft hetzelfde! Het resultaat is een multidimensionale Series:
Let op dat de volgorde waarop je de lijst in groupby opstelt van belang is. In dit geval is Regio eerst, gevolgd door Decennium. Draai je ze om, dan zal het resultaat er zo uitzien:
Je hebt gezien dat je met groupby gegevens kunt groeperen om er vervolgens berekeningen op uit te voeren. Dit kan op één kolom, maar ook op meerdere kolommen tegelijk. Met de agg-methode voer je verschillende berekeningen uit op de gegroepeerde gegevens.
In veel gevallen zul je groupby gebruiken als alternatief voor een draaitabel. Het voordeel is dat je de code eenmalig schrijft en daarna steeds opnieuw kunt gebruiken, ook als er nieuwe gegevens bijkomen. Bovendien kun je de berekeningen precies afstemmen op wat je nodig hebt.
Erwin is de oprichter van python-cursus.nl. In allerlei rollen heeft hij Python ingezet, van het eenvoudiger maken van zijn werk tot het opleveren van complete (web)applicaties. Met vrouw en kinderen woont hij in Havelte (Drenthe), midden in de prachtige natuur. Daar wandelt hij graag, zeker ook omdat de beste ingevingen tijdens een wandeling - weg van de computer - lijken te komen.
Training volgen?
Heb je behoefte aan een in-person training voor jezelf of je team?
Dat kan! Laat je gegevens achter en dan nemen we zo snel mogelijk contact met je op de mogelijkheden te bespreken.
Vragen, opmerkingen?
Heb je vragen, opmerkingen, suggesties of tips naar aanleiding van deze blog?
Neem dan contact met ons op, of laat het weten via
Mastodon of
LinkedIN.