Cara membuat peta pemilihan di R

Jika Anda memetakan hasil pemilihan, katakanlah, pemilihan presiden AS menurut negara bagian, masuk akal untuk hanya menunjukkan satu warna merah untuk negara bagian yang dimenangkan oleh Partai Republik, dan satu warna biru untuk negara bagian yang dimenangkan oleh Demokrat. Itu karena tidak masalah apakah seorang kandidat menang dengan tiga ribu suara atau tiga juta: Ini adalah "pemenang mengambil semua."

Tetapi ketika menganalisis hasil pemilihan negara bagian menurut kabupaten , atau pemilihan seluruh kota berdasarkan polisi , margin itu penting. Itu total keseluruhan yang menentukan pemenang. Memenangkan "Atlanta" itu sendiri bukanlah semua yang perlu Anda ketahui ketika melihat hasil Georgia di seluruh negara bagian untuk gubernur, misalnya. Anda ingin tahu berapa banyak suara yang dimenangkan oleh Demokrat , dan membandingkannya dengan daerah lain. 

Itulah mengapa saya suka membuat peta yang diberi kode warna oleh pemenang dan dengan intensitas warna yang menunjukkan margin kemenangan. Itu memberi tahu Anda area mana yang berkontribusi lebih banyak dan mana yang berkontribusi lebih sedikit pada hasil keseluruhan.

Dalam demo ini, saya akan menggunakan hasil presidensial Pennsylvania 2016. Jika Anda ingin mengikutinya, unduh data dan file bentuk geospasial:

unduh hasil pemilu Pennsylvania 2016 menurut file data pemilu county dan county dan shapefile. Sharon Machlis

Saya pertama kali memuat beberapa paket: dplyr, glue, scale, htmltools, sf, dan leaflet. Saya akan menggunakan rio untuk mengimpor file CSV data, jadi Anda akan menginginkannya di sistem Anda juga.

perpustakaan (dplyr); perpustakaan (lem); perpustakaan (timbangan);

perpustakaan (htmltools); perpustakaan (sf); perpustakaan (leaflet)

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

Impor dan persiapan data

Selanjutnya, saya menggunakan st_read()fungsi sf untuk mengimpor shapefile dari wilayah Pennsylvania.

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

stringsAsFactors = FALSE)

Saya tidak suka nama kolom county COUNTY_NAM di pa_geo, jadi saya akan mengubahnya menjadi “County” dengan kode ini:

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

Sebelum saya menggabungkan data saya dengan geografi saya, saya ingin memastikan bahwa nama kabupaten sama di kedua file. Fungsi dplyr anti_join()menggabungkan dua kumpulan data dan menunjukkan baris mana yang tidak cocok. Saya akan menyimpan hasilnya dalam bingkai data yang disebut masalah dan melihat enam baris pertama dengan head () dan tiga kolom pertama:

masalah <- anti_join (pa_geo, pa_data, oleh = "County")

kepala (masalah [, 1: 3])

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

Ada satu baris masalah. Itu karena McKean County adalah MCKEAN dalam data ini, sedangkan McKEAN dalam bingkai data lainnya. Saya akan mengubah McKean menjadi huruf besar semua dalam pa_data dan menjalankan anti_join()pemeriksaan lagi.

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

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

Sekarang seharusnya tidak ada baris masalah.

Baris kode berikutnya menggabungkan data dengan geografi:

pa_map_data <- merge (pa_geo, pa_data, oleh = "County")

Akhirnya, saya akan memastikan bahwa geografi dan objek data baru saya menggunakan proyeksi yang sama seperti petak selebaran saya. Proyeksi adalah topik GIS yang cukup kompleks. Untuk saat ini, ketahuilah bahwa saya memerlukan WGS84 untuk mencocokkan selebaran. Kode ini menetapkan proyeksi saya:

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

Sekarang data saya sudah dalam bentuk yang saya butuhkan, saya punya tiga tugas lagi: Membuat palet warna untuk setiap kandidat, membuat pop-up untuk peta, dan kemudian membuat kode untuk peta itu sendiri.

Palet warna

Saya akan mulai dengan palet.

Saya akan memetakan perbedaan suara mentah dalam demo ini, tetapi Anda mungkin ingin menggunakan perbedaan persentase. Baris pertama pada kode di bawah ini menggunakan range()fungsi basis R untuk mendapatkan selisih suara terkecil dan terbesar pada kolom Margin. Saya telah menetapkan warna paling terang ke angka terkecil, dan yang paling gelap ke angka terbesar. 

Selanjutnya saya membuat dua palet, menggunakan warna merah konvensional untuk Partai Republik dan biru untuk Demokrat. Saya menggunakan skala intensitas yang sama untuk kedua palet: paling ringan untuk margin terendah, terlepas dari kandidat, dan tertinggi untuk margin tertinggi, terlepas dari kandidat. Ini akan memberi saya gambaran di mana setiap kandidat terkuat dalam satu skala intensitas. Saya menggunakan colorNumeric()fungsi selebaran , dengan warna palet Merah atau Biru, untuk membuat palet. ( domainArgumen menetapkan nilai minimum dan maksimum untuk skala warna.)

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

Grup kode berikutnya membuat  dua bingkai data yang berbeda : Satu untuk setiap kandidat, hanya berisi tempat yang dimenangkan kandidat. Memiliki dua bingkai data membantu saya mengontrol pop-up dan warna dengan baik. Saya bahkan dapat menggunakan teks pop-up yang berbeda untuk masing-masing. 

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

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

Muncul tiba-tiba

Tugas selanjutnya adalah pop-up tersebut. Di bawah ini saya menghasilkan beberapa HTML termasuk  tag kuat untuk teks tebal dan tag br untuk jeda baris. Jika Anda tidak terbiasa dengan lem, kode di dalam kurung {} adalah variabel yang dievaluasi. Di pop-up, saya akan menampilkan nama kandidat yang menang diikuti dengan total suara mereka, nama kandidat lainnya dan total suara, dan margin kemenangan di negara itu. The  scales::comma() Fungsi menambahkan koma untuk total suara numerik dari seribu atau lebih, dan  accuracy = 1memastikan itu adalah bilangan bulat bulat tanpa poin desimal.

Kode kemudian menyalurkan glue()string teks itu ke dalam HTML()fungsi htmltools  , selebaran mana yang perlu menampilkan teks pop-up dengan benar. 

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

Pemenang: Trump

Trump: {skala :: koma (trump_df $ Trump, akurasi = 1)}

Clinton: {timbangan :: koma (trump_df $ Clinton, akurasi = 1)}

Margin: {skala :: koma (trump_df $ Margin, akurasi = 1)} ")%>%

lapply (htmltools :: HTML)

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

Pemenang: Clinton

Clinton: {timbangan :: koma (clinton_df $ Clinton, akurasi = 1)}

Trump: {timbangan :: koma (clinton_df $ Trump, akurasi = 1)}

Margin: {skala :: koma (clinton_df $ Margin, akurasi = 1)} ")%>%

lapply (htmltools :: HTML)

Kode peta

Akhirnya, peta. Kode peta dimulai dengan membuat objek leaflet dasar menggunakan leaflet() tanpa menambahkan data sebagai argumen di objek utama. Itu karena saya akan menggunakan dua kumpulan data yang berbeda. Baris berikutnya dalam kode di bawah ini menetapkan ubin latar belakang ke CartoDB Positron. (Itu opsional. Anda dapat menggunakan default, tapi saya suka gaya itu.)

selebaran ()%>%

addProviderTiles ("CartoDB.Positron")

Selanjutnya saya akan menggunakan addPolygons()fungsi leaflet dua kali, satu untuk setiap frame data kandidat yang dilapisi pada layer peta yang sama.

selebaran ()%>%

addProviderTiles ("CartoDB.Positron")%>%

addPolygons (

data = trump_df,

fillColor = ~ trump_palette (trump_df $ Margin),

label = trump_popup,

stroke = BENAR,

smoothFactor = 0,2,

fillOpacity = 0.8,

color = "# 666",

berat = 1

)%>%

addPolygons (

data = clinton_df,

fillColor = ~ clinton_palette (clinton_df $ Margin),

label = clinton_popup,

stroke = BENAR,

smoothFactor = 0,2,

fillOpacity = 0.8,

color = "# 666",

berat = 1

)

Pada blok kode di atas, saya mengatur data untuk setiap addPolygons() fungsi ke bingkai data masing-masing kandidat. The fillColorArgumen mengambil palet masing-masing kandidat dan berlaku untuk marjin kemenangan mereka. Pop-up (sebenarnya rollover label) akan menjadi HTML kandidat itu, yang saya buat di atas.

Selebihnya desain standar. strokemenetapkan garis batas di sekitar setiap poligon. smoothFactor menyederhanakan tampilan garis poligon; Saya menyalin nilai dari peta demo RStudio yang saya suka. Dan fillOpacityitulah yang Anda harapkan.

coloradalah warna garis batas poligon , bukan poligon itu sendiri ( warna poligon telah disetel dengan fillColor). weightadalah ketebalan garis batas poligon dalam piksel. 

Kode itu menghasilkan peta seperti di bawah ini, tetapi dengan kemampuan tambahan untuk menggulirkan mouse Anda (atau mengetuk di ponsel) dan melihat data yang mendasarinya. 

Sharon Machlis,

Philadelphia ada di kanan bawah. Anda dapat melihat betapa pentingnya, dari segi populasi, dibandingkan dengan semua wilayah Pennsylvania lainnya yang besar di peta tetapi memiliki pemilih yang jauh lebih sedikit. 

Sharon Machlis,

Mungkin menarik untuk memetakan perbedaan dalam margin suara mentah antara satu pemilu dan pemilu lainnya, seperti Pennsylvania pada 2016 vs. 2020. Peta itu akan menunjukkan di mana pola bergeser paling banyak dan mungkin membantu menjelaskan perubahan dalam hasil di seluruh negara bagian.

Jika Anda tertarik dengan visualisasi data pemilu lainnya, saya telah membuat paket pemilu2 R tersedia di GitHub. Anda dapat menginstalnya sebagaimana adanya atau memeriksa kode R saya di GitHub dan menyesuaikannya untuk Anda gunakan sendiri.

Untuk tips lebih lanjut, kunjungi halaman Do More With R.