渡部恒雄氏の指摘
この見出しを見ると、「読売新聞のナベツネ」を想像する方も多いかと思いますが、笹川平和財団上席フェローの渡部恒雄氏のことです。渡部氏は「多くの人が共和党圧勝だったというが、本当は僅差だった」との講演の中でおっしゃっており、本当にそうか自分で視覚化したくなりました。そこで、年末年始、しこしことRでプログラム組んでみました。私のような初心者が地図に選挙の勝敗具合を色分けするなんて、生成AIのない時代なら考えられないことで、chatGPTが出てわずか2年余りなのに隔世の感がありますね。
Rでのアメリカ本土の地図の作り方
実に簡単にアメリカの地図を手に入れることができます。以下の2文です。
states_map <- sf::st_as_sf(maps::map("state", plot = FALSE, fill = TRUE))
us_map_plot <- ggplot2::ggplot(data = states_map)
上記のようにmaps::map("state")で本土49州の地図が手に入ります。ちなみにstate_mapsデータは以下のようになります。geom列に緯度経度データが入っています。その後の調整も多少必要ですが、生成AIに頼めばうまく調整してくれます。
> print(states_map)
Simple feature collection with 49 features and 1 field
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
Geodetic CRS: +proj=longlat +ellps=clrk66 +no_defs +type=crs
First 10 features:
ID geom
alabama alabama MULTIPOLYGON (((-87.46201 3...
arizona arizona MULTIPOLYGON (((-114.6374 3...
arkansas arkansas MULTIPOLYGON (((-94.05103 3...
california california MULTIPOLYGON (((-120.006 42...
colorado colorado MULTIPOLYGON (((-102.0552 4...
connecticut connecticut MULTIPOLYGON (((-73.49902 4...
delaware delaware MULTIPOLYGON (((-75.80231 3...
district of columbia district of columbia MULTIPOLYGON (((-77.13731 3...
florida florida MULTIPOLYGON (((-85.01548 3...
georgia georgia MULTIPOLYGON (((-80.89018 3...
なお、アラスカ州とハワイ州は含まれていませんのでその点は注意が必要です。また、独立13州は混み入っているので、その拡大図を作るとよいでしょう。
得票率データを可視化する
データはWikipediaよりデータを取りました。2012年、2016年、2020年、2024年の4回分について視覚化しました。なお、2024年選挙はまだ確定していないため暫定値です。
地図を色分けするにあたって、以下の式を用いました。正なら共和党が勝利、負なら民主党が勝利を意味します。ただし、ほかの候補者への投票や無効票もあるので、この両者を足して100になるわけではないことは記しておきます。
(共和党候補者の得票パーセンテージ) - (民主党候補者の得票パーセンテージ)
Rコード
# ライブラリの読み込み
library(conflicted)
library(tidyverse)
library(sf)
library(maps)
library(arrow)
conflict_prefer('filter', 'dplyr')
conflict_prefer('map', 'maps')
#出力する図のfile形式(拡張子)を指定
extension <- c(".png")
# 北東部の州だけを抽出
northeast_states <- c("maine", "new hampshire", "vermont", "massachusetts",
"rhode island", "connecticut", "new york", "new jersey",
"pennsylvania", "delaware", "maryland", "district of columbia",
"virginia")
# アメリカの州境界データを取得
states_map <- st_as_sf(map("state", plot = FALSE, fill = TRUE)) |>
mutate(state = ID)
valid_states <- states_map$state
df_cleaned <- read_parquet("president_vote_us_2012_2024.parquet")
summarytools::dfSummary(df_cleaned)
#alaskaとhawaiiの2州が除外されているか確認
df_deleted <- filter(.data = df_cleaned, !state %in% valid_states)
#2州を削除したデータフレーム
df_cleaned_2 <- filter(.data = df_cleaned, state %in% valid_states)
#49州の緯度経度境界データをleft_join()で追加
df_n_percent <- left_join(states_map, df_cleaned_2, by = "state")
df <- select(.data = df_n_percent, ID, state, Republican_percent,
Democratic_percent, year, geom) |>
mutate(dif = (Republican_percent - Democratic_percent) * 100)
#塗分け比率を固定
dif_range <- range(df$dif, na.rm = TRUE)
northeast_map <- filter(.data = df, state %in% northeast_states)
# --------------------------------
# 全米地図作成
# --------------------------------
purrr::map(sheet_names, ~{
map_states_map <- filter(.data = df, year == .x)
us_map_plot <- ggplot(data = map_states_map) +
geom_sf(aes(fill = dif), color = "black", size = 0.2) + # difで塗り分け
scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0,
name = "share values",
limits = dif_range) + # カラースケール
geom_sf_text(aes(label = ifelse(is.na(dif), "",
paste0(ID, "\n", round(dif, 1)))),
size = 3, color = "black") + # 州名とdifを表示
theme_minimal() + # テーマを調整
labs(title = str_c("US States by Difference between Republican and Democratic vote share ", .x),
subtitle = "State names and share values(if positive, Republican win)",
fill = "share values") +
theme(legend.position = "bottom")
# 指定したファイル形式で地図を保存(全米地図)
ggsave(str_c("us_states_map_", .x, extension),
plot = us_map_plot, width = 4093, height = 2894, units = "px")
# --------------------------------
# 北東部地図作成
# --------------------------------
map_northeast_map <- filter(.data = northeast_map, year == .x)
northeast_map_plot <- ggplot(data = map_northeast_map) +
geom_sf(aes(fill = dif), color = "black", size = 0.2) + # difで塗り分け
scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0,
name = "share values",
limits = dif_range) + # カラースケール
geom_sf_text(aes(label = ifelse(is.na(dif), "",
paste0(ID, "\n", round(dif, 1)))),
size = 3, color = "black") + # 州名とdifを表示
coord_sf(xlim = c(-80, -66), ylim = c(36, 47)) + # 地図の範囲を制限
theme_minimal() + # テーマを調整
labs(title = str_c("Northeast US States by Difference between Republican and Democratic vote share ", .x),
subtitle = "State names and share values(if positive, Republican win)",
fill = "share values") +
theme(legend.position = "bottom")
# 指定したファイル形式で地図を保存(北東部地図)
ggsave(str_c("northeast_states_map_", .x, extension),
plot = northeast_map_plot, width = 4093, height = 2894, units = "px")
})
アウトプットの一部紹介(2020年と2024年の州別得票率地図)
ただ並べただけではわかりづらいですが、gifファイルにしてアニメーションにするなどしてみると、2020→2024で赤は濃く、青は薄くなっていることがわかります。例えばカリフォルニア州のように圧倒的民主党が有利なところでも2020年-30→2024年-20となっています。これは2020年の選挙で民主党に投票していた人のうち5%の人が共和党に乗り換えたのと同義です。実際にパネルデータ化して解析したところ、有意差があるとの結果でした。
まとめ
このように地図にすることは、現在ではとても簡単になっています。むしろ得票率データを手に入れクレンジングすることのほうが、よほど時間がかかります。データ解析の結果を可視化することのハードルは大きく下がっていますので、どんどん活用していきましょう。
最後に表題の私なりの回答です。「確かに僅差だけど、やはり流れは相当トランプに向いており、戦前の予想を加味すると『圧勝』という印象を人間は持つよね」。