GeoPandas ist ein Modul für Python das die Arbeit mit Visualisierung und Grafiken vereinfacht.

Es baut dabei auf die Datentypen von pandas auf und erweitert diese um räumliche Operationen an geometrischen Typen. Dazu wird auf Bibliotheken wie shapely, fiona und matplotlib zurückgegriffen. GeoPandas verbindet diese Tools und bietet so eine Programmierschnittstelle auf einer high-Level-Ebene.

In diesem Tutorial zeige ich dir wie du GeoPandas installierst und für ein einfaches Datenvisualisierungsprojekt - bei dem die Länder auf einer Weltkarte anhand der E-Sport-Preisgelder von Spielern aus dem jeweiligen Land eingefärbt werden - benutzt.

Schritt #1 Installiere GeoPandas

Viele Wege führen nach Rom. Manche führen auch zu einer Installation von GeoPandas. Zwei Wege wie du GeoPandas installierst, werde ich dir vorstellen.

Weg 1: GeoPandas mit Anaconda/Miniconda installieren

Installationsanweisungen für Anaconda findest du auf der Webseite des Projekts. Nach der Installation hast du auch das conda Programm auf deinem Computer installiert. Hiermit lassen sich - ähnlich wie mit pip - weitere Pakete installieren.

Jetzt kannst du Geopandas und alle Abhängigkeiten mit conda installieren.

conda install geopandas

Für schönere Grafiken solltest du auch noch matplotlib und mapclassify installieren.

conda install matplotlib
conda install mapclassify

Weg 2: GeopPandas mit Pip installieren

Alternativ dazu lassen sich die Abhängigkeiten natürlich auch manuell installieren. Anschließend kannst du GeoPandas auch mit Pip installieren.

Um die Abhängigkeiten auf Windows zum laufen zu bringen musst du zunächst folgende Dateien von Christoph Gohlke / University of California herunterladen:

Für GDAL brauchst du auf Windows die Microsoft Visual C++ Build Tools v142. Die kannst du mit dem Visual Studio Installer von Microsoft installieren.

Anschließend kannst du die heruntergeladenen Wheel-Pakete installieren.

pip install wheel

pip install Fiona-1.8.19-cp39-cp39-win_amd64.whl
pip install Shapely-1.7.1-cp39-cp39-win_amd64.whl
pip install Rtree-0.9.7-cp39-cp39-win_amd64.whl
pip install pyproj-3.0.1-cp39-cp39-win_amd64.whl

pip install geopandas

Für schönere Grafiken solltest du auch noch matplotlib und mapclassify installieren.

pip install matplotlib
pip install mapclassify

Schritt #2 Installiere das Kartenmaterial

Als Basis für Projekte mit Weltkarten brauchst du natürlich eine Weltkarte. Außerdem musst du GeoPandas sagen, wo auf der Karte welches Land liegt. Glücklicherweise haben schon andere Menschen genau diese Arbeit für dich übernommen.

Zum einen gibt es Karten die bereits in Geopandas integriert sind. Eine dieser Karten lässt sich mit folgendem Code einlesen.

import geopandas
gdf = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
gdf.plot()

Dieser Datensatz ist - wie der Name schon vermuten lässt - nicht sehr hoch aufgelöst. Es fehlen einige kleine Länder wie zum Beispiel Singapur.

Datensätze mit höherer Auflösung kannst du beim public domain Projekt naturalearthdata.com herunterladen.

Für dieses Projekt habe ich mich für Medium scale data, 1:50m –> Cultural –> Admin 0 - Countries entschieden. Dieses musst du in deinen Projektordner entpacken und schon kannst du mit Python darauf zugreifen.

import geopandas

shapefile = r"mapfiles\countries\ne_50m_admin_0_countries.shp"

gdf = geopandas.read_file(shapefile)[
    ["ADMIN", "ADM0_A3", "geometry", "POP_EST"]
]

Schritt #3 Präpariere die Rohdaten

Für dieses Beispiel will ich eine Karte haben, die Preisgelder aus dem E-Sport anzeigt. Die Rohdaten hierzu habe ich von esportsearnings.com heruntergeladen und in eine CSV (hier semicolon separated) Datei geschrieben.

Um diese Daten mit der Karte von Naturalearthdata zu verbinden, musste ich noch eine Spalte mit ISO Country Codes hinzufügen. Dies ist mühsame Arbeit und kommt bei fast allen Data Science und Data Analytics Projekten vor.

USA;United States;165427090
CHN;China;127035376
KOR;Korea, Republic of;99904605
SWE;Sweden;40011972
DNK;Denmark;39609229
FRA;France;32621027
RUS;Russian Federation;31139007
CAN;Canada;29873091
DEU;Germany;29008052
FIN;Finland;26269125
GBR;United Kingdom;23192694
BRA;Brazil;22308144
AUS;Australia;18218456
UKR;Ukraine;16600569
POL;Poland;15057102
TWN;Taiwan, Republic of;12235319
JPN;Japan;10697051
NLD;Netherlands;10307609
MYS;Malaysia;10263513
PHL;Philippines;9039836
NOR;Norway;8551531
THA;Thailand;8141558
BGR;Bulgaria;7979555
JOR;Jordan;6816906
ESP;Spain;6690313
VNM;Viet Nam;4751742
LBN;Lebanon;4467585
TUR;Turkey;4408552
PAK;Pakistan;4321837
EST;Estonia;4226763
AUT;Austria;3949509
SGP;Singapore;3933302
ARG;Argentina;3828150
ROU;Romania;3720056
ITA;Italy;3650439
ISR;Israel;3471858
BEL;Belgium;3327065
HKG;Hong Kong;3160220
MEX;Mexico;2982098
KAZ;Kazakhstan;2868810
IDN;Indonesia;2712964
CZE;Czech Republic;2671262
SAU;Saudi Arabia;2570690
BLR;Belarus;2399602
PER;Peru;2396587
SVK;Slovakia;2169438
CHE;Switzerland;1828872
PRT;Portugal;1790063
GRC;Greece;1767980
MAC;Macao;1583511
NZL;New Zealand;1561816
LTU;Lithuania;1240053
SVN;Slovenia;1190350
BIH;Bosnia and Herzegovina;1169045
MKD;Macedonia, The Former Yugoslav Republic of;1142826
CHL;Chile;1105297
HRV;Croatia;1084631
HUN;Hungary;1083067
SRB;Serbia;1029757
ZAF;South Africa;970373
LVA;Latvia;968605
IND;India;964439
IRL;Ireland;824712
UZB;Uzbekistan;665682
MNG;Mongolia;560428
KGZ;Kyrgyzstan;492843
DOM;Dominican Republic;438139
COL;Colombia;390282
ARE;United Arab Emirates;344930
ARM;Armenia;340283
URY;Uruguay;305496
PRI;Puerto Rico;284497
BOL;Bolivia;283171
MDA;Moldova, Republic of;272798
TUN;Tunisia;225975
IRN;Iran, Islamic Republic of;209404
ISL;Iceland;179581
AZE;Azerbaijan;173904
VEN;Venezuela;167643
EGY;Egypt;165020
MAR;Morocco;156179
MNE;Montenegro;152671
IRQ;Iraq;145933
MLT;Malta;145118
AFG;Afghanistan;144724
KWT;Kuwait;104905
CUB;Cuba;94216
GEO;Georgia;90125
DZA;Algeria;89534
ALB;Albania;86571
BHR;Bahrain;75607
CRI;Costa Rica;73413
LUX;Luxembourg;49598
SYR;Syrian Arab Republic;49553
KHM;Cambodia;43146
PAN;Panama;43046
KOS;Kosovo, Republic of;42286
LAO;Lao People's Democratic Republic;39225
GTM;Guatemala;36621
NPL;Nepal;35154
NIC;Nicaragua;30938
BGD;Bangladesh;30610
ECU;Ecuador;29655
QAT;Qatar;24192
ETH;Ethiopia;23669
OMN;Oman;20970
PSX;Palestinian Territory, Occupied;20836
MMR;Myanmar;19773
LKA;Sri Lanka;16669
PRY;Paraguay;13679
FRO;Faroe Islands;9525
GRL;Greenland;8825
SLV;El Salvador;6709
BRN;Brunei Darussalam;6636
MUS;Mauritius;5355
YEM;Yemen;3840
NCL;New Caledonia;3412
FLK;Falkland Islands;2987
GHA;Ghana;2808
MCO;Monaco;2301
HND;Honduras;1836
ZMB;Zambia;1635
KEN;Kenya;1632
CYP;Cyprus;1577
TTO;Trinidad and Tobago;1138
AND;Andorra;940
SEN;Senegal;750
GUY;Guyana;700
MDG;Madagascar;458
JAM;Jamaica;377
MNP;Northern Mariana Islands;300
BHS;Bahamas;263
BLZ;Belize;250
PYF;French Polynesia;245
TKM;Turkmenistan;220
BMU;Bermuda;200
MDV;Maldives;121
GGY;Guernsey;100
IMN;Isle of Man;75
JEY;Jersey;60
LIE;Liechtenstein;56
SUR;Suriname;56
MAF;Saint Martin;50
KNA;Saint Kitts and Nevis;20
ABW;Aruba;14
BLM;Saint-Barthélemy;7

Schritt #4 Plotte den Graphen

Jetzt wo alle Vorbereitungen abgeschlossen sind kannst du mit dem eigentlichen Programmieren beginnen. In diesem Beispiel habe ich die Antarktis entfernen, um Platz zu sparen.

Hier nochmal der komplette Code:

# Bibliotheken importieren
import geopandas
import pandas
import matplotlib.pyplot as plt

# Karte einlesen
shapefile = r"mapfiles\countries\ne_50m_admin_0_countries.shp"
gdf.columns = ["country_code", "geometry"]

#Antarktis entfernen
gdf = gdf[gdf.name != "Antarctica"]

# Preisgelder einlesen
earningsdf = pandas.read_csv(
    "data.csv", sep=";", names=["code", "name", "pricemoney"]
)

# Preisgelder in Karte integrieren
merged = gdf.merge(
    earningsdf, left_on="country_code", right_on="code", how="left"
)

# Nicht genannte Länder auf 0 $ setzen
merged["pricemoney"] = merged["pricemoney"].fillna(0)

# Plotten
fig, ax = plt.subplots(1, figsize=(15, 15))
p = merged.plot(
    column="pricemoney",
    legend=True,
    ax=ax,
    cmap="OrRd",
    scheme="FisherJenks",
    legend_kwds={
        "loc": "lower left",
        "title": "Price money in USD",
    },
)

# Hintergrundfarbe setzen
p.set_facecolor("gray")

# Achsenbeschriftung entfernen
ax.set_yticklabels([])
ax.set_xticklabels([])

# Grafik speichern
plt.savefig("pricemoneyPerCountry.jpg", bbox_inches="tight", dpi=300)

Das Scheme “FisherJenks” ist übrigens von mapClassify. Weitere Schemes findest du hier. Am besten spielst du mal mit unterschiedlichen davon herum.

So sieht das Endresultat aus

Fazit

Die Nerven aufreibendsten Punkte waren für mich beim Recherchieren die Installation mit Pip sowie die Bereinigung der Rohdaten. Sobald das geschafft ist, lässt sich das Resultat aber gut angucken.

Vor allem für das Aussehen der Grafik kann man viel Zeit verwenden. Guckt euch dazu am besten die Dokumentationen von Matplotlib, Mapclassify und natürlich Geopandas an.

Ich habe leider noch keinen schönen Weg gefunden die Einheiten in der Legende lesbarer zu gestalten. Am besten ist es wohl, wenn man eine eigene Legende zeichnet.

Ansonsten gibt es noch zu sagen, dass du je nach Zielgruppe mit den Karten aufpassen solltest. Nicht alle Länder werden von allen Menschen anerkannt. Kritische Gebiete sind zum Beispiel Hongkong, Kosovo, Macau, Taiwan oder die Krim.


Konnte ich helfen? Ich freue mich über einen Drink! 💙