So erstellen Sie eine Wahlkarte in R.

Wenn Sie beispielsweise die Wahlergebnisse der US-Präsidentschaftswahlen nach Bundesstaaten abbilden, kann es sinnvoll sein, nur eine Farbe Rot für Staaten anzuzeigen, die von Republikanern gewonnen wurden, und eine Farbe Blau für Staaten, die von Demokraten gewonnen wurden. Das liegt daran, dass es keine Rolle spielt, ob ein Kandidat mit dreitausend oder drei Millionen Stimmen gewinnt: Es ist „Gewinner nehmen alle“.

Bei der Analyse der Ergebnisse einer Landtagswahl nach Landkreisen oder einer stadtweiten Wahl nach Bezirken spielt jedoch der Spielraum eine Rolle. Es ist die Gesamtsumme, die über den Gewinner entscheidet. Der Gewinn von „Atlanta“ selbst ist nicht alles, was Sie wissen müssen, wenn Sie beispielsweise die landesweiten Ergebnisse für den Gouverneur in Georgia betrachten. Sie würden wissen wollen , wie viele Stimmen der Demokraten gewann durch , und vergleichen Sie das mit anderen Bereichen. 

Aus diesem Grund erstelle ich gerne Karten, die vom Gewinner farbcodiert sind und deren Farbintensität die Gewinnspanne anzeigt. Das zeigt Ihnen, welche Bereiche mehr und welche weniger zum Gesamtergebnis beigetragen haben.

In dieser Demo werde ich die Ergebnisse des Präsidenten von Pennsylvania 2016 verwenden. Wenn Sie mitmachen möchten, laden Sie die Daten und Geodaten herunter:

Download der Wahlergebnisse für Pennsylvania 2016 nach County und County Shapefiles Wahldatendatei und Shapefile. Sharon Machlis

Ich lade zuerst einige Pakete: dplyr, kleber, Waage, htmltools, sf und Faltblatt. Ich werde Rio verwenden, um die Daten-CSV-Datei zu importieren, also möchten Sie das auch auf Ihrem System.

Bibliothek (dplyr); Bibliothek (Kleber); Bibliothek (Waage);

Bibliothek (htmltools); Bibliothek (sf); Bibliothek (Faltblatt)

pa_data <- rio :: import ("pa_2016_presidential.csv")

Datenimport und Vorbereitung

Als nächstes verwende ich die st_read()Funktion von sf , um ein Shapefile der Grafschaften von Pennsylvania zu importieren.

pa_geo <- sf :: st_read ("PaCounty2020_08 / PaCounty2020_08.shp",

stringAsFactors = FALSE)

Ich mag den County-Spaltennamen COUNTY_NAM in pa_geo nicht, daher werde ich ihn mit diesem Code in "County" ändern:

Namen (pa_geo) [2] <- "Grafschaft"

Bevor ich meine Daten mit meiner Geografie zusammenführe, möchte ich sicherstellen, dass die County-Namen in beiden Dateien identisch sind. Die anti_join()Funktion von dplyr führt zwei Datensätze zusammen und zeigt an, welche Zeilen nicht übereinstimmen. Ich werde die Ergebnisse in einem Datenrahmen speichern, der als Probleme bezeichnet wird, und die ersten sechs Zeilen mit head () und die ersten drei Spalten betrachten:

Probleme <- anti_join (pa_geo, pa_data, by = "County")

Kopf (Probleme [, 1: 3])

MSLINK County COUNTY_NUM Geometrie 1 42 MCKEAN 42 MULTIPOLYGON (((-78.20638 4 ...

Es gibt eine Problemzeile. Das liegt daran, dass McKean County in diesen Daten MCKEAN ist, im anderen Datenrahmen jedoch McKEAN. Ich werde McKean so ändern, dass alle Kappen in pa_data stehen, und die anti_join()Prüfung erneut ausführen .

pa_data $ County [pa_data $ County == "McKEAN"] <- "MCKEAN"

anti_join (pa_geo, pa_data, by = "County")

Es sollte jetzt keine Problemzeilen geben.

In der nächsten Codezeile werden die Daten mit der Geografie zusammengeführt:

pa_map_data <- zusammenführen (pa_geo, pa_data, by = "County")

Schließlich werde ich sicherstellen, dass mein neues Geografie- und Datenobjekt dieselbe Projektion verwendet wie meine Flugblattkacheln. Projektion ist ein ziemlich komplexes GIS-Thema. Im Moment weiß ich nur, dass ich WGS84 brauche, um mit der Packungsbeilage übereinzustimmen. Dieser Code legt meine Projektion fest:

pa_map_data <- st_transform (pa_map_data, "+ proj = longlat + datum = WGS84")

Jetzt, da meine Daten die gewünschte Form haben, habe ich drei weitere Aufgaben: Erstellen Sie Farbpaletten für jeden Kandidaten, erstellen Sie Popups für die Karte und codieren Sie dann die Karte selbst.

Farbpaletten

Ich werde mit den Paletten beginnen.

Ich werde in dieser Demo rohe Abstimmungsunterschiede abbilden , aber Sie können stattdessen prozentuale Unterschiede verwenden. In der ersten Zeile des folgenden Codes wird die range()Funktion von Basis R verwendet, um die kleinsten und größten Abstimmungsunterschiede in der Spalte "Rand" zu erhalten. Ich habe der kleinsten Zahl die hellste Farbe und der größten Zahl die dunkelste Farbe zugewiesen. 

Als nächstes erstelle ich zwei Paletten, wobei ich das konventionelle Rot für Republikaner und das Blau für Demokraten verwende. Ich verwende für beide Paletten dieselbe Intensitätsskala: am leichtesten für den niedrigsten Rand, unabhängig vom Kandidaten, und am höchsten für den höchsten Rand, unabhängig vom Kandidaten. Dies gibt mir eine Vorstellung davon, wo jeder Kandidat auf einer einzelnen Intensitätsskala am stärksten war. Ich verwende die colorNumeric()Funktion der Broschüre mit einer Palettenfarbe von Rot oder Blau, um die Paletten zu erstellen. (Das domainArgument legt Mindest- und Höchstwerte für die Farbskala fest.)

min_max_values ​​<- range (pa_map_data $ Margin, na.rm = TRUE)

trump_palette <- colorNumeric (palette = "Reds",

domain = c (min_max_values ​​[1], min_max_values ​​[2]))

clinton_palette <- colorNumeric (palette = "Blues",

domain = c (min_max_values ​​[1], min_max_values ​​[[2]]))

Die nächste Codegruppe erstellt  zwei verschiedene Datenrahmen : einen für jeden Kandidaten, der nur die Plätze enthält, die der Kandidat gewonnen hat. Mit zwei Datenrahmen kann ich die Popups und Farben genau steuern. Ich kann sogar für jeden einen anderen Popup-Text verwenden. 

trump_df <- pa_map_data [pa_map_data $ Winner == "Trump",]

clinton_df <- pa_map_data [pa_map_data $ Winner == "Clinton",]

Popups

Die nächste Aufgabe sind diese Popups. Im Folgenden generiere ich HTML-Code, einschließlich  starker Tags für fett gedruckten Text und br- Tags für Zeilenumbrüche. Wenn Sie mit Klebstoff nicht vertraut sind, sind die Codes in den {} Klammern Variablen, die ausgewertet werden. In den Popups werde ich den Namen des siegreichen Kandidaten anzeigen, gefolgt von seiner Stimmenzahl, dem Namen und der Stimmenzahl des anderen Kandidaten und der Gewinnspanne in diesem Landkreis. Die  scales::comma() Funktion fügt numerischen Stimmen von tausend oder mehr ein Komma hinzu und accuracy = 1stellt sicher ,  dass es sich um eine runde Ganzzahl ohne Dezimalstellen handelt.

Der Code leitet diese glue()Textzeichenfolge dann an die HTML()Funktion von htmltools weiter  . In dieser Broschüre muss der Popup-Text ordnungsgemäß angezeigt werden. 

trump_popup <- kleber (" {trump_df $ County} COUNTY

Gewinner: Trump

Trump: {scale :: comma (trump_df $ Trump, Genauigkeit = 1)}

Clinton: {scale :: comma (trump_df $ Clinton, Genauigkeit = 1)}

Margin: {scale :: comma (trump_df $ Margin, Genauigkeit = 1)} ")%>%

lapply (htmltools :: HTML)

clinton_popup <- kleber (" {clinton_df $ County} COUNTY

Gewinner: Clinton

Clinton: {scale :: comma (clinton_df $ Clinton, Genauigkeit = 1)}

Trump: {scale :: comma (clinton_df $ Trump, Genauigkeit = 1)}

Margin: {scale :: comma (clinton_df $ Margin, Genauigkeit = 1)} ")%>%

lapply (htmltools :: HTML)

Kartencode

Endlich die Karte. Der Kartencode beginnt mit der Erstellung eines grundlegenden Faltblattobjekts, bei dem leaflet() keine Daten als Argument im Hauptobjekt hinzugefügt werden. Das liegt daran, dass ich zwei verschiedene Datensätze verwenden werde. In der nächsten Zeile im folgenden Code werden die Hintergrundkacheln auf CartoDB Positron gesetzt. (Das ist optional. Sie können die Standardeinstellung verwenden, aber ich mag diesen Stil.)

Faltblatt ()%>%

addProviderTiles ("CartoDB.Positron")

Als nächstes werde ich die addPolygons()Funktion der Broschüre zweimal verwenden, eine für den Datenrahmen jedes Kandidaten, der auf derselben Kartenebene überlagert ist.

Faltblatt ()%>%

addProviderTiles ("CartoDB.Positron")%>%

addPolygons (

data = trump_df,

fillColor = ~ trump_palette (trump_df $ Margin),

label = trump_popup,

Strich = WAHR,

glattFaktor = 0,2,

fillOpacity = 0.8,

color = "# 666",

Gewicht = 1

)%>%

addPolygons (

data = clinton_df,

fillColor = ~ clinton_palette (clinton_df $ Margin),

label = clinton_popup,

Strich = WAHR,

glattFaktor = 0,2,

fillOpacity = 0.8,

color = "# 666",

Gewicht = 1

)

Im obigen Codeblock setze ich die Daten für jede addPolygons() Funktion auf den Datenrahmen jedes Kandidaten. Das fillColorArgument nimmt die Palette jedes Kandidaten und wendet sie auf seine Gewinnspanne an. Das Popup (eigentlich ein Rollover label) ist der HTML- Code des Kandidaten, den ich oben erstellt habe.

Der Rest ist Standarddesign. strokeLegt eine Grenzlinie um jedes Polygon fest. smoothFactor vereinfacht die Anzeige der Polygonkonturen; Ich habe den Wert von einer RStudio-Demo-Map kopiert, die mir gefallen hat. Und fillOpacityist das, was Sie erwarten würden.

colorist die Farbe der Polygon - Grenzlinie , nicht das Polygon selbst (die Polygonfarbe mit gesetzt wurde fillColor). weightist die Dicke der Polygongrenzlinie in Pixel. 

Dieser Code generiert eine Karte wie die folgende, bietet jedoch die Möglichkeit, mit der Maus darüber zu fahren (oder auf das Handy zu tippen) und die zugrunde liegenden Daten anzuzeigen. 

Sharon Machlis,

Philadelphia ist unten rechts. Sie können sehen, wie wichtig es in Bezug auf die Bevölkerung im Vergleich zu allen anderen Gebieten von Pennsylvania ist, die auf der Karte groß sind, aber weit weniger Wähler haben. 

Sharon Machlis,

Es könnte interessant sein, den Unterschied in den rohen Abstimmungsrändern zwischen einer Wahl und einer anderen, wie beispielsweise Pennsylvania im Jahr 2016 gegenüber 2020, abzubilden. Diese Karte würde zeigen, wo sich die Muster am stärksten verschoben haben, und könnte dazu beitragen, Änderungen der landesweiten Ergebnisse zu erklären.

Wenn Sie an weiteren Visualisierungen von Wahldaten interessiert sind, habe ich ein Elections2 R-Paket auf GitHub verfügbar gemacht. Sie können es entweder unverändert installieren oder meinen R-Code auf GitHub überprüfen und für Ihren eigenen Gebrauch anpassen.

Weitere R-Tipps finden Sie auf der Seite Mehr mit R tun.