Programmering

Hvordan lage et valgkart i R

Hvis du kartlegger valgresultatene for for eksempel det amerikanske presidentvalget etter stat, kan det være fornuftig å bare vise en rød farge for stater vunnet av republikanere, og en farge blå for stater vunnet av demokrater. Det er fordi det ikke betyr noe om en kandidat vinner med tre tusen stemmer eller tre millioner: Det er "vinneren tar alt."

Men når man analyserer resultatene av en statsvalg av fylke, eller a byomspennende valg av distriktet, marginen betyr noe. Det er den totale summen som avgjør vinneren. Å vinne "Atlanta" i seg selv er ikke alt du trenger å vite når du for eksempel ser på statlige resultater fra Georgia for guvernør. Du vil vite hvor mange stemmer demokraten vant av, og sammenlign det med andre områder.

Derfor liker jeg å lage kart som er fargekodet av vinneren og med fargeintensitet som viser seiersmargin. Det forteller deg hvilke områder som bidro mer og hvilke som bidro mindre til det samlede resultatet.

I denne demonstrasjonen vil jeg bruke presidentresultatene i Pennsylvania 2016. Hvis du vil følge med, laster du ned dataene og geospatiale formfilene:

last ned valgresultat i Pennsylvania 2016 etter fylkes- og fylkesformer Valgdatafil og formfil. Sharon Machlis

Jeg laster først inn noen pakker: dplyr, lim, vekter, htmltools, sf og folder. Jeg bruker rio til å importere CSV-filen, så du vil også ha den på systemet ditt.

bibliotek (dplyr); bibliotek (lim); bibliotek (skalaer);

bibliotek (htmltools); bibliotek (sf); bibliotek (brosjyre)

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

Dataimport og prep

Deretter bruker jeg sf’s st_read () funksjon for å importere en shapefile av Pennsylvania fylker.

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

stringsAsFactors = FALSE)

Jeg liker ikke fylkeskolonnenavnet COUNTY_NAM i pa_geo, så jeg vil endre det til "Fylke" med denne koden:

navn (pa_geo) [2] <- "County"

Før jeg slår sammen dataene mine med geografien, vil jeg sørge for at fylkesnavnene er de samme i begge filene. dplyr’s anti_join () funksjon slår sammen to datasett og viser hvilke rader ikke gjør det ha en kamp. Jeg lagrer resultatene i en dataramme kalt problemer og ser på de seks første radene med hodet () og de tre første kolonnene:

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

hode (problemer [, 1: 3])

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

Det er en problemrekke. Det er fordi McKean County er MCKEAN i disse dataene, men McKEAN i den andre datarammen. Jeg endrer McKean til å være alle caps i pa_data og kjører anti_join () Sjekk igjen.

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

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

Det skal nå ikke være noen problemrader.

Neste kodelinje slår sammen dataene med geografien:

pa_map_data <- flett (pa_geo, pa_data, etter = "County")

Til slutt skal jeg sørge for at min nye geografi og dataobjekt bruker det samme projeksjon som mine brosjyrer gjør. Projeksjon er et ganske komplekst GIS-tema. Foreløpig, bare vet at jeg trenger WGS84 for å matche brosjyren. Denne koden angir projeksjonen min:

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

Nå som dataene mine er i den formen jeg trenger, har jeg tre oppgaver til: Lag fargepaletter for hver kandidat, lag popup-vinduer for kartet, og kod deretter selve kartet.

Fargepaletter

Jeg begynner med palettene.

Jeg skal kartlegge rå stemmeforskjeller i denne demoen, men det kan være lurt å bruke prosentvise forskjeller i stedet. Den første linjen i koden nedenfor bruker R-er område() funksjon for å få de minste og største stemmeforskjellene i Margin-kolonnen. Jeg har tilordnet den lyseste fargen til det minste tallet, og den mørkeste til det største tallet.

Deretter lager jeg to paletter, som bruker det vanlige røde for republikanere og blått for demokrater. Jeg bruker samme intensitetsskala for begge palettene: lettest for laveste margin, uavhengig av kandidat, og høyest for høyeste margin, uavhengig av kandidat. Dette vil gi meg en ide om hvor hver kandidat var sterkest på en enkelt intensitetsskala. Jeg bruker brosjyrer colorNumeric () funksjon, med en palettfarge på Reds eller Blues, for å lage palettene. (De domene argumentet angir minimums- og maksimumsverdier for fargeskalaen.)

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]]))

Den neste kodegruppen oppretterto forskjellige datarammer: Én for hver kandidat, som bare inneholder plassene kandidaten vant. Å ha to datarammer hjelper meg å få fin kontroll over popup-vinduer og farger. Jeg kan til og med bruke forskjellig popup-tekst for hver.

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

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

Pop-ups

Neste oppgave er disse popup-vinduene. Nedenfor genererer jeg litt HTML inkludertsterk koder for fet tekst og br koder for linjeskift. Hvis du ikke er kjent med lim, er koden i {} parentesene variabler som evalueres. I popup-vinduene viser jeg navnet på den vinnende kandidaten etterfulgt av stemmesummen, den andre kandidatens navn og stemmetotal og seiersmarginen i det fylket. Deskalaer :: komma () funksjonen legger et komma til det numeriske stemmesumet på tusen eller mer, ognøyaktighet = 1 sørger for at det er et rundt heltall uten desimaltegn.

Koden rør deretter den lim() tekststreng til htmltools ’HTML () funksjonen, hvilken brosjyre må vise popup-teksten ordentlig.

trump_popup <- lim ("{trump_df $ County} Fylke

Vinner: Trump

Trump: {skalerer :: komma (trump_df $ Trump, nøyaktighet = 1)}

Clinton: {skalerer :: komma (trump_df $ Clinton, nøyaktighet = 1)}

Margin: {skalerer :: komma (trump_df $ Margin, nøyaktighet = 1)} ")%>%

lapply (htmltools :: HTML)

clinton_popup <- lim ("{clinton_df $ County} Fylke

Vinner: Clinton

Clinton: {skalerer :: komma (clinton_df $ Clinton, nøyaktighet = 1)}

Trump: {skalerer :: komma (clinton_df $ Trump, nøyaktighet = 1)}

Margin: {skalerer :: komma (clinton_df $ Margin, nøyaktighet = 1)} ")%>%

lapply (htmltools :: HTML)

Kartkode

Endelig kartet. Kartkoden starter med å lage et grunnleggende brosjyreobjekt ved hjelp av brosjyre () uten legge til data som et argument i hovedobjektet. Det er fordi jeg skal bruke to forskjellige datasett. Neste linje i koden nedenfor setter bakgrunnsfliser til CartoDB Positron. (Det er valgfritt. Du kan bruke standard, men jeg liker den stilen.)

brosjyre ()%>%

addProviderTiles ("CartoDB.Positron")

Neste bruker jeg brosjyrer addPolygons () funksjon to ganger, en for hver kandidats dataramme overlagt på samme kartlag.

brosjyre ()%>%

addProviderTiles ("CartoDB.Positron")%>%

addPolygons (

data = trump_df,

fillColor = ~ trump_palette (trump_df $ Margin),

etikett = trump_popup,

hjerneslag = SANT,

smoothFactor = 0,2,

fillOpacity = 0,8,

color = "# 666",

vekt = 1

) %>%

addPolygons (

data = clinton_df,

fillColor = ~ clinton_palette (clinton_df $ Margin),

etikett = clinton_popup,

hjerneslag = SANT,

smoothFactor = 0,2,

fillOpacity = 0,8,

color = "# 666",

vekt = 1

)

I kodeblokken ovenfor angir jeg dataene for hver addPolygons () funksjon til hver kandidats dataramme. De Fyll farge argumentet tar hver kandidats palett og bruker den på seiersmarginen. Pop-up (faktisk en rollover merkelapp) vil være kandidatens HTML, som jeg opprettet ovenfor.

Resten er standard design. hjerneslag setter en kantlinje rundt hver polygon. smoothFactor forenkler polygon omrissvisning; Jeg kopierte verdien fra et RStudio demo-kart jeg likte. Og fillOpacity er det du forventer.

farge er fargen på polygon kantlinje, ikke selve polygonet (polygonet farge ble satt med Fyll farge). vekt er tykkelsen på polygongrenselinjen i piksler.

Den koden genererer et kart som det nedenfor, men med den ekstra muligheten til å rulle musen over (eller trykke på mobil) og se underliggende data.

Sharon Machlis,

Philadelphia er nederst til høyre. Du kan se hvor viktig det er, befolkningsmessig, sammenlignet med alle andre områder i Pennsylvania som er store på kartet, men som har langt færre velgere.

Sharon Machlis,

Det kan være interessant å kartlegge forskjell i rå stemme marginer mellom ett valg og et annet, som Pennsylvania i 2016 mot 2020. Det kartet viser hvor mønstrene skiftet mest og kan være med på å forklare endringer i statlige resultater.

Hvis du er interessert i flere visualiseringsdata for valg, har jeg gjort en valg2 R-pakke tilgjengelig på GitHub. Du kan enten installere den som den er eller sjekke ut R-koden min på GitHub og skreddersy den til eget bruk.

For flere R-tips, gå til ’Do More With R-siden.

$config[zx-auto] not found$config[zx-overlay] not found