Pandas: Groupby Beispiele¶
In diesem Teil unseres Python- und Pandas-Kurses möchten wir ein ausführliches Beispiel für die Verwendung von groupby geben. Wir werden eine Datendatei [donations.txt] (https://python-course.eu/data/donations.txt) verwenden.
Die ersten Zeilen dieser Datendatei sehen wie folgt aus:
firstname,surname,city,job,income,donations
Janett,Schwital,Karlsruhe,Politician,244400,2512
Daniele,Segebahn,Freiburg,Student,16800,336
Kirstin,Klapp,Hamburg,Engineer,116900,1479
Oswald,Segebahn,Köln,Musician,57700,1142
Heinz-Joachim,Wagner,Stuttgart,Engineer,109300,1592
Die Daten dieser Datei wurden mit Hilfe des Python-Faker-Moduls künstlich erzeugt, eine mögliche Übereinstimmung mit real existierenden Personen ist also rein zufällig und nicht beabsichtigt. Jede Zeile enthält den Vor- und Nachnamen einer fiktiven Person sowie den Wohnort, die berufliche Position (einer der fünf Berufe Politiker, Student, Ingenieur, Musiker und Manager), das frühe Einkommen und die Summe der Spenden pro Jahr.
Zunächst lesen wir die Datendatei ein, die trotz der Endung 'txt' natürlch eine csv-Datei ist:
import pandas as pd
fname = 'data1/donations.txt'
data = pd.read_csv(fname, usecols=[2, 3, 4, 5])
data[:10]
Schauen wir uns zunächst an, wie viel jede Berufsgruppe insgesamt verdient und gespendet hat. Dazu können wir die Pandas-Funktion groupby
zusammen mit sum
verwenden:
data_sum = data.groupby(['job']).sum()
data_sum
Durch die Verwendung von "sort_values" für die Spalte "donations" können wir diesen DataFrame sortieren:
data_sum.sort_values(by='donations')
Schauen wir uns die folgenden drei Personen aus unserem Datei an:
Janett,Schwital,Karlsruhe,Politician,244400,2512
Daniele,Segebahn,Freiburg,Student,16800,336
Kirstin,Klapp,Hamburg,Engineer,116900,1479
Wer ist der großzügigste von ihnen? Die Politikerin Janett Schwital? 2512 Euro sind doch fast achtmal so viel wie das, was die Studentin Daniele Segebahn gespendet hat, und fast zweimal so viel wie die Ingenieurin Kirstin Klapp gespendet hat.
Die meisten Menschen würden denken, dass wir die Spenden in Relation zu ihren Einkommen sehen müssen. Dann erhalten wir folgendes:
Der Politikerin hat etwa 1 % ihres Einkommens gespendet, die Ingenieurin etwa 1,3 % und die Studentin 2 %. Wir können also sagen, dass Daniele im Verhältnis zu ihrem Einkommen am großzügigsten ist!
Machen wir das Gleiche mit dem vorherigen DataFrame:
data_sum['relative'] = data_sum.donations * 100 / data_sum.income
data_sum.sort_values(by='relative')
Wir sehen also, dass die Manager und Managerinnen und die Politikerinnen und Politiker sehr knauserig sind und die Studierenden extrem großzügig sind. Können wir dies verallgemeinern, indem wir sagen: Je weniger Leute haben, desto großzügiger sind sie. Jedoch darf man nicht vergessen, dass der ganze Datensatz gefälscht ist!
Wir wollen nun die Anzahl der Personen in jeder Berufsgruppe für jede Stadt zählen. Die Verwendung von "count" und "groupby" in der folgenden Weise ist hilfreich, aber nicht schön. Die Zahlen in den Spalten "Einkommen" und "Spenden" zeigen die gewünschten Zahlen, aber die Spaltennamen sind irreführend und wir brauchen die Ergebnisse nicht doppelt:
x = data.groupby(['city', 'job']).count()
x
Wir könnten das Folgende tun, um ein gutes Ergebnis zu erzielen, aber der ganze Weg ist ungeschickt:
people_job_city = data.groupby(['city', 'job']).count()
people_job_city.drop(columns=['income'], inplace=True)
people_job_city.rename(columns={'donations': 'number of people'})
Der bessere Weg besteht darin, groupby
von Pandas zu benutzen. In der folgenden Lösung gruppiert die groupby
-Methode den DataFrame nach den angegebenen Spalten (in diesem Fall "city" und "job") und erstellt für jede Gruppe einen neuen DataFrame. Die size
-Methode gibt die Anzahl jeder Gruppe zurück, was zu einem neuen DataFrame mit den Anzahlen für jede Kombination von Stadt und Stelle führt. Beachten Sie, dass das Ergebnis ein Series-Objekt ist:
result = data[['city', 'job']].groupby(['city', 'job']).size()
result
Interessanter als das vorherige Ergebnis ist die Anzahl der Spenden und insbesondere die Spenden im Verhältnis zum Einkommen für jeden Job und jede Stadt:
city_job_data = data.groupby(['city', 'job']).sum()
city_job_data[:12] # the first 12 lines
Auch hier ziehen wir es vor, die Spenden im Verhältnis zu den Einnahmen zu sehen:
city_job_data['rel_donations'] = (city_job_data['donations'] * 100 / city_job_data['income']).round(2)
city_job_data.drop(['income', 'donations'], axis=1, inplace=True)
city_job_data[:12]
Vielleicht wollen Sie jetzt wissen, in welcher Stadt die großzügigsten Menschen leben?
cities_donations = data.groupby(['city']).sum()
cities_donations['relative'] = cities_donations['donations'] * 100 / cities_donations['income']
cities_donations.sort_values(by='relative')