AONF Project

  • RStudioで公開中
# =================================================================
# AONF Project: Standard Graph Format
# =================================================================

# 1. 共通設定(スクリプトの冒頭で一度だけ実行)
library(ggplot2)

# ブログタイトルの定義
# 英語と日本語の間に改行 (\n) あり
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 2. グラフ作成の基本構成
# 以下をコピーして、データと変数名を書き換えて使用してください
ggplot(data = [データフレーム名], aes(x = [X軸], y = [Y軸], fill = [色分け])) +
  geom_bar(stat = "identity") + # または geom_point(), geom_line() など
  labs(
    title = "ここにタイトルを入力",
    subtitle = "ここにサブタイトルを入力",
    x = "X軸ラベル",
    y = "Y軸ラベル",
    fill = "凡例名",
    caption = AONF_CAPTION  # 共通設定を呼び出し
  ) +
  # 指定のフォントとミニマルテーマを適用
  theme_minimal(base_family = "HiraKakuProN-W3") + 
  theme(
    legend.position = "bottom",
    # キャプションのスタイルを統一
    plot.caption = element_text(size = 8, color = "grey30", lineheight = 1.2, margin = margin(t = 15))
  )

1. 自治体選管のデータ

行橋市

1

library(ggplot2)

# =================================================================
# AONF Project: Standard Graph Format
# =================================================================

# 1. 共通設定(スクリプトの冒頭で定義)
# 英語と日本語の間に改行 (\n) を入れることで、モバイル表示でも美しく収まります
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 行橋市の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
  district_votes = c(11815, 1041, 13915, 4751, 2843), # 小選挙区
  pr_votes = c(4202, 839, 13362, 5787, 2799)         # 比例代表
)

# COR (候補者超過達成比率) の計算
# $COR = \frac{\text{小選挙区得票}}{\text{比例政党得票}}$
election_data$cor <- election_data$district_votes / election_data$pr_votes

# 2. グラフ作成
ggplot(election_data, aes(x = reorder(candidate, -cor), y = cor, fill = party)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_text(aes(label = round(cor, 2)), vjust = -0.5, size = 4) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") +
  # 縦軸の範囲を調整
  scale_y_continuous(limits = c(0, 3.2)) +
  # カスタムカラー設定
  scale_fill_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
    coord_fixed() +
  labs(
    title = "行橋市における候補者超過達成比率 (COR)",
    subtitle = "第51回衆院選 (2026) 確定データに基づく分析\n※赤の破線はCOR=1.0(比例票と小選挙区票が一致)を示す",
    x = "候補者",
    y = "COR (小選挙区得票 / 比例政党得票)",
    fill = "政党名",
    caption = AONF_CAPTION  # 共通設定を呼び出し
  ) +
  # 指定のフォントとミニマルテーマを適用
  theme_minimal(base_family = "HiraKakuProN-W3") + 
  theme(
    legend.position = "bottom",
    # キャプションのスタイルを統一
    plot.caption = element_text(size = 8, color = "grey30", lineheight = 1.2, margin = margin(t = 15))
  )

2

library(ggplot2)

# 1. AONF形式: キャプション変数の定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"


# 行橋市の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
  district_votes = c(11815, 1041, 13915, 4751, 2843), # 小選挙区
  pr_votes = c(4202, 839, 13362, 5787, 2799)          # 比例代表
)

# 相関図の作成
ggplot(election_data, aes(x = pr_votes, y = district_votes, color = party)) +
  geom_point(size = 4) +
  # 凡例の「a」を消去するための設定
  geom_text(aes(label = candidate), vjust = -1.5, family = "HiraKakuProN-W3",show.legend = FALSE) +
  # COR=1.0 の基準線 (y = x)
  geom_abline(intercept = 0, slope = 1, linetype = "dashed",color = "red", alpha = 0.5) +
  scale_x_continuous(limits = c(0, 15000)) +
  scale_y_continuous(limits = c(0, 15000)) +
  scale_color_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
  coord_fixed() +
  
  # 2. AONF形式: labsでの適用
  labs(title = "政党得票数と候補者得票数の相関図(行橋市)",
       subtitle = "第51回衆院選 (2026)確定データ\n ※赤い破線は COR = 1.0 (小選挙区票 = 比例票) を示す",
       x = "政党得票数(比例代表)",
       y = "候補者得票数(小選挙区)",
       caption = AONF_CAPTION) +
  # 3. AONF形式: themeの一括指定
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom", 
        plot.caption = element_text(size = 8, hjust = 1, color = "gray30"))

田川市

1

library(ggplot2)

# =================================================================
# AONF Project: Standard Graph Format
# =================================================================

# 1. 共通設定
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 田川市の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
  district_votes = c(6109, 1113, 8654, 2981, 1362), # 小選挙区
  pr_votes = c(2197, 860, 7322, 3794, 1530)         # 比例代表
)

# CORの計算
election_data$cor <- election_data$district_votes / election_data$pr_votes

# 2. グラフ作成
ggplot(election_data, aes(x = reorder(candidate, -cor), y = cor, fill = party)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_text(aes(label = round(cor, 2)), vjust = -0.5, size = 4) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") +
  # 縦軸の範囲を調整
  scale_y_continuous(limits = c(0, 3.2)) +
  # カスタムカラー設定
  scale_fill_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
  
    coord_fixed() +
  labs(
    title = "田川市における候補者超過達成比率 (COR)",
    subtitle = "第51回衆院選 (2026) 確定データに基づく分析\n※赤の破線はCOR=1.0(比例票と小選挙区票が一致)を示す",
    x = "候補者",
    y = "COR (小選挙区得票 / 比例政党得票)",
    fill = "政党名",
    caption = AONF_CAPTION  # 共通設定を呼び出し
  ) +
  # AONF標準テーマ設定
  theme_minimal(base_family = "HiraKakuProN-W3") + 
  theme(
    legend.position = "bottom",
    # キャプションのスタイルを統一
    plot.caption = element_text(size = 8, color = "grey30", lineheight = 1.2, margin = margin(t = 15))
  )

2

library(ggplot2)


# 1. 共通設定
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 田川市の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
 district_votes = c(6109, 1113, 8654, 2981, 1362), # 小選挙区
  pr_votes = c(2197, 860, 7322, 3794, 1530)         # 比例代表
)


# 相関図の作成
ggplot(election_data, aes(x = pr_votes, y = district_votes, color = party)) +
  geom_point(size = 4) +
  # show.legend = FALSE を追加して凡例の「a」を消去
  geom_text(aes(label = candidate), vjust = -1.5, family = "HiraKakuProN-W3", show.legend = FALSE) +
  # COR=1.0 の基準線 (y = x)
  geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "red", alpha = 0.5) +
  scale_x_continuous(limits = c(0, 9300)) +
  scale_y_continuous(limits = c(0, 9300)) +
   scale_color_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
  coord_fixed() +
    labs(title = "政党得票数と候補者得票数の相関図(田川市)",
       subtitle = "第51回衆院選 (2026) 確定データ\n※ 赤い破線は COR = 1.0 (小選挙区票 = 比例票) を示す",
       x = "政党得票数(比例代表)",
       y = "候補者得票数(小選挙区)",

       caption = AONF_CAPTION) +
  # 3. AONF形式: themeの一括指定
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom", 
        plot.caption = element_text(size = 8, hjust = 1, color = "gray30"))

苅田町

1

library(ggplot2)

# =================================================================
# AONF Project: Standard Graph Format
# =================================================================

# 1. 共通設定
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 苅田町の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
  district_votes = c(4818, 470, 6084, 2365, 1541), # 小選挙区
  pr_votes = c(1695, 308, 5784, 2702,1414 )         # 比例代表
)

# CORの計算
election_data$cor <- election_data$district_votes / election_data$pr_votes

# 2. グラフ作成
ggplot(election_data, aes(x = reorder(candidate, -cor), y = cor, fill = party)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_text(aes(label = round(cor, 2)), vjust = -0.5, size = 4) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") +
  # 縦軸の範囲を調整
  scale_y_continuous(limits = c(0, 3.2)) +
  # カスタムカラー設定
  scale_fill_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
  
    coord_fixed() +
  labs(
    title = "苅田町における候補者超過達成比率 (COR)",
    subtitle = "第51回衆院選 (2026) 確定データに基づく分析\n※赤の破線はCOR=1.0(比例票と小選挙区票が一致)を示す",
    x = "候補者",
    y = "COR (小選挙区得票 / 比例政党得票)",
    fill = "政党名",
    caption = AONF_CAPTION  # 共通設定を呼び出し
  ) +
  # AONF標準テーマ設定
  theme_minimal(base_family = "HiraKakuProN-W3") + 
  theme(
    legend.position = "bottom",
    # キャプションのスタイルを統一
    plot.caption = element_text(size = 8, color = "grey30", lineheight = 1.2, margin = margin(t = 15))
  )

2

library(ggplot2)

# 1. 共通設定
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 苅田町の確定データ (2026年 第51回衆院選)
election_data <- data.frame(
  candidate = c("村上 智信", "しき 玲子", "武田 良太", "辻 智之", "井上なおき"),
  party = c("維新", "社民", "自民", "中道", "参政"),
 district_votes = c(4818, 470, 6084, 2365, 1541), # 小選挙区
  pr_votes = c(1695, 308, 5784, 2702,1414 )       # 比例代表
)


# 相関図の作成
ggplot(election_data, aes(x = pr_votes, y = district_votes, color = party)) +
  geom_point(size = 4) +
  # show.legend = FALSE を追加して凡例の「a」を消去
  geom_text(aes(label = candidate), vjust = -1.5, family = "HiraKakuProN-W3", show.legend = FALSE) +
  # COR=1.0 の基準線 (y = x)
  geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "red", alpha = 0.5) +
  scale_x_continuous(limits = c(-100, 7000)) +
  scale_y_continuous(limits = c(-100, 7000)) +
   scale_color_manual(values = c("自民" = "#3536C1", "維新" = "#31D925", 
                                "中道" = "#E9EB3B", "社民" = "#EB3B3B", "参政" = "orange")) +
  coord_fixed() +
    labs(title = "政党得票数と候補者得票数の相関図(苅田町)",
       subtitle = "第51回衆院選 (2026)\n※ 赤い破線は COR = 1.0 (小選挙区票 = 比例票) を示す",
       x = "政党得票数(比例代表)",
       y = "候補者得票数(小選挙区)",

       caption = AONF_CAPTION) +
  # 3. AONF形式: themeの一括指定
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom", 
plot.caption = element_text(size = 8, hjust = 1, color = "gray30"))

地域比較

# 必要なパッケージの読み込み
# インストールされていない場合は install.packages("ggplot2") を実行してください
library(ggplot2)


AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# 1. データの作成
# これまでの会話やソースで確認された中道改革連合候補(辻氏)のCORデータ
df_tsuji_cor <- data.frame(
  Municipality = factor(c("行橋市", "田川市", "苅田町"), levels = c("行橋市", "田川市", "苅田町")),
  COR = c(0.82, 0.79, 0.88)
)

# 作成日の取得(資料のスクリプトスタイルを踏襲)
today <- as.character(Sys.Date())

# 2. 棒グラフの作成
ggplot(df_tsuji_cor, aes(x = Municipality, y = COR, fill = Municipality)) +
  # 棒グラフの描画
  geom_bar(stat = "identity", width = 0.5) +
  # 棒の上に数値を表示
  geom_text(aes(label = COR), vjust = -0.5, size = 5) +
  # 基準となるCOR 1.0のラインを赤い点線で追加
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red", size = 1) +
  # タイトルとラベルの設定
  labs(
    title = "中道改革連合候補(辻智之氏)の地域別COR比較",
# subtitle = paste("作成日:", today, " - 点線はCOR 1.0 (政党基礎票と等しいライン)"),
 subtitle = "点線はCOR 1.0 (政党基礎票と等しいライン)",
    x = "開票区",
    y = "COR (候補者超過達成比率)",
caption = AONF_CAPTION)   +
  
    # Y軸の範囲を設定 (1.0のラインが見えるように上限を1.1に)
  scale_y_continuous(limits = c(0, 1.1)) +
  # 棒の色を地域ごとに指定
  scale_fill_manual(values = c("行橋市" = "steelblue", "田川市" = "darkorange", "苅田町" = "forestgreen")) +


  # AONF標準テーマ設定
  theme_minimal(base_family = "HiraKakuProN-W3") + 
  theme(
    legend.position = "bottom",
    # キャプションのスタイルを統一
    plot.caption = element_text(size = 8, color = "grey30", lineheight = 1.2, margin = margin(t = 15))
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

得票率

田川市

library(ggplot2)
library(dplyr)
## 
## 次のパッケージを付け加えます: 'dplyr'
## 以下のオブジェクトは 'package:stats' からマスクされています:
## 
##     filter, lag
## 以下のオブジェクトは 'package:base' からマスクされています:
## 
##     intersect, setdiff, setequal, union
library(scales)

# AONF形式のキャプション定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# データの読み込み(ヘッダーなし、V1:政党名, V2:得票数)
df <- read.csv("田川市.csv", header = FALSE, stringsAsFactors = FALSE)
colnames(df) <- c("Party", "Votes")

# 1. 得票数のクリーニング(カンマの除去)と数値変換
df$Votes <- as.numeric(gsub(",", "", df$Votes))

# 2. 得票率の計算
df <- df %>%
  mutate(Percentage = (Votes / sum(Votes)) * 100) %>%
  arrange(desc(Percentage)) # 降順にソート

# 3. グラフの作成(AONF/標準フォーマット適用)
p <- ggplot(df, aes(x = reorder(Party, Percentage), y = Percentage)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  coord_flip() + # 横棒グラフ
  geom_text(aes(label = sprintf("%.1f%%", Percentage)), hjust = -0.1) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title = "田川市 比例代表 各党得票率(衆院選2026年)",
    x = "政党名",
    y = "得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2)
  )

# グラフの表示
print(p)

# 計算結果の確認(コンソール出力用)
print(df)
##           Party Votes Percentage
## 1        自民党  7322  36.321246
## 2          中道  3794  18.820378
## 3          維新  2197  10.898358
## 4          参政  1530   7.589662
## 5        民主党  1140   5.655042
## 6        共産党  1054   5.228434
## 7        社民党   860   4.266085
## 8        れいわ   816   4.047820
## 9        みらい   771   3.824594
## 10       保守党   406   2.013989
## 11 ゆうこく連合   269   1.334392

行橋市

library(ggplot2)
library(dplyr)
library(scales)

# 1. AONF_CAPTION 変数の定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# データの読み込み
# 行橋.tsv は タブ区切り、ヘッダーなし、2列目(得票数)にカンマを含む形式を想定
data <- read.table("行橋.tsv", sep="\t", header=FALSE, col.names=c("party", "votes"), stringsAsFactors=FALSE)

# 文字列から数値を抽出(カンマを除去して数値型に変換)
data$votes_num <- as.numeric(gsub(",", "", data$votes))

# 得票率の計算と並び替え
data <- data %>%
  mutate(percentage = (votes_num / sum(votes_num)) * 100) %>%
  arrange(desc(percentage))

# 政党名の順序を固定(グラフの並び順に反映)
data$party <- factor(data$party, levels = rev(data$party))

# グラフ作成
ggplot(data, aes(x = party, y = percentage)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  geom_text(aes(label = sprintf("%.1f%%", percentage)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, max(data$percentage) + 5)) +
  # 2. labs(caption = AONF_CAPTION) の使用
  labs(title = "行橋市 比例代表 各党得票率(衆院選2026年)",
       x = "政党名",
       y = "得票率 (%)",
       caption = AONF_CAPTION) +
  # 3. theme_minimal(base_family = ...) と theme(legend.position = "bottom", plot.caption = ...) の適用
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2),
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text = element_text(size = 10)
  )

苅田町

library(ggplot2)
library(dplyr)
library(scales)
library(readr)
## 
## 次のパッケージを付け加えます: 'readr'
## 以下のオブジェクトは 'package:scales' からマスクされています:
## 
##     col_factor
# AONF形式のキャプション定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# データの読み込み(ヘッダーなし、V1:政党名, V2:得票数)
d <- read_csv("苅田町.csv")
## New names:
## • `` -> `...1`
## • `` -> `...2`
## Rows: 11 Columns: 2
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ...1
## num (1): ...2
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df <- as.data.frame(d)
colnames(df) <- c("Party", "Votes")


# 1. 得票数のクリーニング(カンマの除去)と数値変換
df$Votes <- as.numeric(gsub(",", "", df$Votes))

# 2. 得票率の計算
df <- df %>%
  mutate(Percentage = (Votes / sum(Votes)) * 100) %>%
  arrange(desc(Percentage)) # 降順にソート


# 3. グラフの作成(AONF/標準フォーマット適用)
p <- ggplot(df, aes(x = reorder(Party, Percentage), y = Percentage)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  coord_flip() + # 横棒グラフ
  geom_text(aes(label = sprintf("%.1f%%", Percentage)), hjust = -0.1) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title = "苅田町 比例代表 各党得票率(衆院選2026年)",
    x = "政党名",
    y = "得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2)
  )

# グラフの表示
print(p)

# 計算結果の確認(コンソール出力用)
print(df)
##                     Party Votes Percentage
## 1              自由民主党  5784  37.702888
## 2            中道改革連合  2702  17.612933
## 3            日本維新の会  1695  11.048823
## 4                  参政党  1414   9.217131
## 5              国民民主党  1252   8.161137
## 6            チームみらい   754   4.914934
## 7            れいわ新選組   443   2.887687
## 8              日本保守党   414   2.698651
## 9              日本共産党   386   2.516133
## 10             社会民主党   308   2.007692
## 11 減税日本・ゆうこく連合   189   1.231993

2. 県選管データ

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ lubridate 1.9.4     ✔ tibble    3.3.0
## ✔ purrr     1.2.0     ✔ tidyr     1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ readr::col_factor() masks scales::col_factor()
## ✖ purrr::discard()    masks scales::discard()
## ✖ dplyr::filter()     masks stats::filter()
## ✖ dplyr::lag()        masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(scales)

# AONF形式の定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# データの読み込み
df <- read.csv("fukuoka11ku2026.csv", check.names = FALSE)

# データの加工:カンマ削除、数値変換、得票率の計算
df_long <- df %>%
  mutate(across(-Municipality, ~as.numeric(gsub(",", "", .)))) %>%
  pivot_longer(-Municipality, names_to = "Candidate", values_to = "Votes") %>%
  group_by(Municipality) %>%
  mutate(Share = Votes / sum(Votes)) %>%
  ungroup() %>%
  # 自治体名の空白をトリミング(必要に応じて)
  mutate(Municipality = trimws(Municipality))

# グラフ作成
p <- ggplot(df_long, aes(x = Municipality, y = Share, fill = Candidate)) +
  geom_bar(stat = "identity", position = "fill") +
  scale_y_continuous(labels = percent) +
  labs(
    title = "福岡11区 自治体別候補者得票率",
    subtitle = "衆議院議員選挙2026年",
    x = "自治体",
    y = "得票率",
    fill = "候補者",
    caption = AONF_CAPTION
  ) +
  # AONF標準形式のテーマ適用
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

# グラフの保存
ggsave("fukuoka11ku_voteshare.png", p, width = 10, height = 7, dpi = 300)
library(tidyverse)
library(scales)

# AONF形式の定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# データの読み込み
df <- read.csv("fukuoka11ku2026.csv", check.names = FALSE)

# データの加工
df_clean <- df %>%
  # カンマを削除して数値化
  mutate(across(-Municipality, ~as.numeric(gsub(",", "", .)))) %>%
  # 自治体ごとの総得票数を計算
  mutate(Total_Votes = rowSums(select(., -Municipality))) %>%
  # 自治体名の空白をトリミング
  mutate(Municipality = trimws(Municipality))

# プロット用にロング形式に変換し、総得票数で並べ替え
df_long <- df_clean %>%
  pivot_longer(cols = c(Tsuji, Takeda, Shiki, Inoue, Murakami), 
               names_to = "Candidate", values_to = "Votes") %>%
  mutate(Share = Votes / Total_Votes) %>%
  # MunicipalityをTotal_Votesの降順で因子(factor)化する
  mutate(Municipality = fct_reorder(Municipality, Total_Votes, .desc = TRUE))

# グラフ作成
p <- ggplot(df_long, aes(x = Municipality, y = Share, fill = Candidate)) +
  geom_bar(stat = "identity", position = "fill") +
  scale_y_continuous(labels = percent) +
  labs(
    title = "2026年衆議院議員選挙福岡11区 自治体別候補者得票率",
    subtitle = "左から総得票数が多い順に自治体を並べています",
    x = "自治体",
    y = "得票率",
    fill = "候補者",
    caption = AONF_CAPTION
  ) +
  # AONF標準形式のテーマ適用
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

# グラフの保存
ggsave("fukuoka11ku_voteshare_sorted.png", p, width = 10, height = 7, dpi = 300)

候補者と政党のデータを合併

library(tidyverse)

# 1. データの読み込み
# Note: read_csvはカンマ入りの数値を文字列として読み込む場合があります
df_candidates <- read_csv("fukuoka11ku2026.csv")
## Rows: 15 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Municipality
## num (5): Tsuji, Takeda, Shiki, Inoue, Murakami
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_parties <- read_csv("福岡11区2026年政党.csv")
## Rows: 15 Columns: 12
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): municipality
## dbl (4): れいわ新選組, 日本保守党, 減税日本・ゆうこく連合, 社会民主党
## num (7): 自由民主党, 中道改革連合, チームみらい, 日本維新の会, 参政党, 国民民主党, 日本共産党...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# 2. 市町村名のクリーニング
# fukuoka11ku2026.csv の地域名に含まれる全角・半角スペースを削除します
df_candidates <- df_candidates %>%
  mutate(Municipality = str_trim(Municipality))

# 3. 合併(マージ)
# 列名が 'Municipality' と 'municipality' で異なるため明示的に結合キーを指定します
df_merged <- df_candidates %>%
  inner_join(df_parties, by = c("Municipality" = "municipality"))

# 4. 数値データの整形(カンマの除去と数値型への変換)
# 地域名以外の列で、カンマが含まれる文字列を数値に変換します
df_merged <- df_merged %>%
  mutate(across(-Municipality, ~ {
    if(is.character(.)) {
      as.numeric(str_remove_all(., ","))
    } else {
      .
    }
  }))

# 5. 結果の書き出し
write_csv(df_merged, "fukuoka11ku2026_merged.csv")

# データの確認
print(head(df_merged))
## # A tibble: 6 × 17
##   Municipality Tsuji Takeda Shiki Inoue Murakami れいわ新選組 日本保守党
##   <chr>        <dbl>  <dbl> <dbl> <dbl>    <dbl>        <dbl>      <dbl>
## 1 田川市        2981   8654  1113  1362     6109          816        406
## 2 行橋市        4751  13915  1041  2843    11815          965        822
## 3 豊前市        1528   5506   440   820     3774          381        271
## 4 香春町         631   2667   201   309     1302          182         97
## 5 添田町         576   2127   148   217     1230          148         78
## 6 糸田町         642   1939   191   255      863          180         65
## # ℹ 9 more variables: 自由民主党 <dbl>, 中道改革連合 <dbl>,
## #   `減税日本・ゆうこく連合` <dbl>, チームみらい <dbl>, 社会民主党 <dbl>,
## #   日本維新の会 <dbl>, 参政党 <dbl>, 国民民主党 <dbl>, 日本共産党 <dbl>
knitr::kable(df_merged)
Municipality Tsuji Takeda Shiki Inoue Murakami れいわ新選組 日本保守党 自由民主党 中道改革連合 減税日本・ゆうこく連合 チームみらい 社会民主党 日本維新の会 参政党 国民民主党 日本共産党
田川市 2981 8654 1113 1362 6109 816 406 7322 3794 269 771 860 2197 1530 1140 1054
行橋市 4751 13915 1041 2843 11815 965 822 13362 5787 461 1553 839 4202 2799 2515 963
豊前市 1528 5506 440 820 3774 381 271 4813 2051 175 542 413 1403 949 650 326
香春町 631 2667 201 309 1302 182 97 2041 1065 62 176 209 481 346 233 199
添田町 576 2127 148 217 1230 148 78 1732 909 38 141 135 467 262 184 184
糸田町 642 1939 191 255 863 180 65 1400 975 67 115 167 330 263 197 124
川崎町 935 3348 283 349 1516 260 88 2473 1653 84 174 216 555 402 258 258
大任町 175 1828 57 106 415 119 36 1291 464 22 58 68 177 159 117 44
赤村 133 878 59 57 378 42 25 646 278 16 70 66 123 88 77 35
福智町 1361 4955 472 655 2223 410 203 3709 1949 149 308 429 824 717 499 390
苅田町 2365 6084 470 1541 4818 443 414 5784 2702 189 754 308 1695 1414 1252 386
みやこ町 1281 4181 271 566 2917 261 160 3743 1706 124 378 264 1083 621 531 284
吉富町 436 1336 107 249 878 87 68 1146 580 45 136 72 262 264 193 156
上毛町 459 1855 124 311 1112 142 93 1632 602 47 183 123 380 299 232 131
築上町 757 3146 210 430 3652 204 167 3339 1229 113 331 236 1306 578 442 212

2.1 対応分析等

福岡11区:候補者と政党の得票構造(ハブ分析)

library(readr)
library(ggplot2)
library(FactoMineR)
library(patchwork)
library(vegan)
## 要求されたパッケージ permute をロード中です
library(igraph)
## 
## 次のパッケージを付け加えます: 'igraph'
## 以下のオブジェクトは 'package:vegan' からマスクされています:
## 
##     diversity
## 以下のオブジェクトは 'package:permute' からマスクされています:
## 
##     permute
## 以下のオブジェクトは 'package:lubridate' からマスクされています:
## 
##     %--%, union
## 以下のオブジェクトは 'package:purrr' からマスクされています:
## 
##     compose, simplify
## 以下のオブジェクトは 'package:tidyr' からマスクされています:
## 
##     crossing
## 以下のオブジェクトは 'package:tibble' からマスクされています:
## 
##     as_data_frame
## 以下のオブジェクトは 'package:dplyr' からマスクされています:
## 
##     as_data_frame, groups, union
## 以下のオブジェクトは 'package:stats' からマスクされています:
## 
##     decompose, spectrum
## 以下のオブジェクトは 'package:base' からマスクされています:
## 
##     union
library(stringr)
library(dplyr)

# --- 定数の定義 (AONF format) ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# --- データの準備 ---
data <- read_csv("fukuoka11ku2026_merged_a.csv")
## Rows: 15 Columns: 17
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (1): Municipality
## dbl (16): Tsuji, Takeda, Shiki, Inoue, Murakami, れいわ, 保守党, 自民党, 中道, ゆうこく連合, ...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
data_clean <- data %>%
  mutate(across(-Municipality, ~ as.numeric(str_remove_all(as.character(.), ","))))

voting_data <- as.data.frame(data_clean[,-1])
rownames(voting_data) <- data_clean$Municipality

# --- 1. 対応分析 (CA) とクラスタリング ---
ca_res <- CA(voting_data, graph = FALSE)
ca_full_coord <- ca_res$col$coord 
ca_hc <- hclust(dist(ca_full_coord), method = "ward.D2")
ca_cluster <- factor(cutree(ca_hc, k = 3))

ca_df <- data.frame(
  Dim1 = ca_full_coord[,1],
  Dim2 = ca_full_coord[,2],
  Name = rownames(ca_full_coord),
  Cluster = ca_cluster
)

# --- 2. MST (最小全域木) データ作成 ---
get_mst_segments <- function(df, dist_obj) {
  mst <- spantree(dist_obj)
  n <- nrow(df)
  data.frame(
    x = df$Dim1[2:n],
    y = df$Dim2[2:n],
    xend = df$Dim1[mst$kid],
    yend = df$Dim2[mst$kid]
  )
}

d_ca <- dist(ca_full_coord)
mst_ca <- spantree(d_ca)
n <- nrow(ca_df)
edges <- cbind(mst_ca$kid, 2:n)
g_mst <- graph_from_edgelist(edges, directed = FALSE)
ca_df$Degree <- degree(g_mst)

# --- 3. 可視化 (Cluster凡例の非表示とスケール固定) ---
p_hub <- ggplot(ca_df, aes(x = Dim1, y = Dim2)) +
  # MSTのネットワーク線
  geom_segment(data = get_mst_segments(ca_df, d_ca), 
               aes(x = x, y = y, xend = xend, yend = yend), 
               color = "gray85", linetype = "solid") +
  # 次数の大きさを点のサイズに反映
  geom_point(aes(color = Cluster, size = Degree), alpha = 0.7) +
  # ラベルの描画
  geom_text(aes(label = Name, color = Cluster), 
            vjust = -1.8, fontface = "bold", 
            family = "HiraKakuProN-W3", show.legend = FALSE) +
  scale_size_continuous(range = c(4, 10)) + 
  scale_color_brewer(palette = "Set1") +
  # ★重要:Clusterの凡例(color)を非表示にする
  guides(color = "none") +
  # 縦横比を1:1に固定
  coord_fixed(ratio = 1, clip = "off") +
  expand_limits(x = range(ca_df$Dim1)*1.5, y = range(ca_df$Dim2)*1.5) +
  # グラフタイトルとAONF形式のキャプション設定
  labs(title = "福岡11区:候補者と政党の得票構造(ハブ分析)", 
       subtitle = "Correspondence Analysis & MST: Hub Identification",
       x = "Dimension 1", 
       y = "Dimension 2", 
       size = "次数 (Hub Strength)",
       caption = AONF_CAPTION) +
  # AONF標準テーマ
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom",
        plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2))

# グラフの表示
print(p_hub)

Greenacre’s Symbiplot

# [Greenacre's Symbiplot]
# AONF_CAPTION の定義
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

#####################################
### symbiplot(Greenacre)
#####################################

if (!require("ca")) install.packages("ca")
## 要求されたパッケージ ca をロード中です
## 
## 次のパッケージを付け加えます: 'ca'
## 以下のオブジェクトは 'package:vegan' からマスクされています:
## 
##     ca
if (!require("ape")) install.packages("ape")
## 要求されたパッケージ ape をロード中です
## 
## 次のパッケージを付け加えます: 'ape'
## 以下のオブジェクトは 'package:igraph' からマスクされています:
## 
##     degree, edges, mst, ring
## 以下のオブジェクトは 'package:dplyr' からマスクされています:
## 
##     where
if (!require("ggrepel")) install.packages("ggrepel")
## 要求されたパッケージ ggrepel をロード中です
library(ca)
library(ape)
library(ggplot2)
library(ggrepel)

# 1. データの読み込み
voting_data <- read.csv("fukuoka11ku2026_merged_a.csv", row.names = 1)

# 【重要】データ構造に合わせて修正
counts <- voting_data[, 1:ncol(voting_data)]

# 2. 対応分析 (CA) の実行
res_ca <- ca(counts)

# 3. Symbiplot用の座標計算
sv_sqrt <- diag(sqrt(res_ca$sv))
rows_coord <- as.data.frame(res_ca$rowcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])
cols_coord <- as.data.frame(res_ca$colcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])

colnames(rows_coord) <- c("Dim1", "Dim2")
rows_coord$Name <- rownames(rows_coord)
rows_coord$Group <- "City"

colnames(cols_coord) <- c("Dim1", "Dim2")
cols_coord$Name <- colnames(counts)
cols_coord$Group <- "Party/Candidate"

# 4. 最小全域木 (MST) の計算
full_principal_coords <- res_ca$colcoord %*% diag(res_ca$sv)
party_dist_chi2 <- dist(full_principal_coords)
st_tree <- mst(party_dist_chi2)

edges <- which(as.matrix(st_tree) == 1, arr.ind = TRUE)
edges <- edges[edges[,1] < edges[,2], ] 

edge_df <- data.frame(
  x = cols_coord$Dim1[edges[,1]], y = cols_coord$Dim2[edges[,1]],
  xend = cols_coord$Dim1[edges[,2]], yend = cols_coord$Dim2[edges[,2]]
)

# 5. 可視化
ggplot() +
  geom_segment(data = edge_df, aes(x=x, y=y, xend=xend, yend=yend), 
               color = "gray60", linetype = "dotted", linewidth = 0.5) +
  geom_point(data = rows_coord, aes(x=Dim1, y=Dim2), color = "blue", alpha = 0.3, size = 1.5) +
  geom_text_repel(data = rows_coord, aes(x=Dim1, y=Dim2, label = Name), 
                  color = "blue", size = 2.5, alpha = 0.6, family="HiraKakuProN-W3") +
  geom_point(data = cols_coord, aes(x=Dim1, y=Dim2), color = "red", size = 3) +
  geom_text_repel(data = cols_coord, aes(x=Dim1, y=Dim2, label = Name), 
                  color = "red", size = 3.5, fontface = "bold", family="HiraKakuProN-W3",
                  box.padding = 0.5, max.overlaps = Inf) +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray80") +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray80") +
  coord_fixed() +
  theme_minimal(base_family="HiraKakuProN-W3") +
  theme(legend.position = "bottom", plot.caption = element_text(size = 7, color = "gray30")) +
  labs(title = "Greenacre's Symbiplot with MST",
       subtitle = "Scaling: Standard Coordinates * sqrt(Singular Values)",
       x = paste0("Dimension 1 (", round((res_ca$sv[1]^2/sum(res_ca$sv^2))*100, 1), "%)"),
       y = paste0("Dimension 2 (", round((res_ca$sv[2]^2/sum(res_ca$sv^2))*100, 1), "%)"),
       caption = AONF_CAPTION)

対応分析のみ(2026年データ)

library(ggrepel) # ラベル重なり防止用

# --- 定数の定義 (AONF format) ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# --- 1. 対応分析 (CA) とデータ準備 ---
# (計算部分は前回の内容を継承)
ca_res <- FactoMineR::CA(voting_data, graph = FALSE)
ca_full_coord <- ca_res$col$coord 
ca_hc <- hclust(dist(ca_full_coord), method = "ward.D2")
ca_cluster <- factor(cutree(ca_hc, k = 3))

ca_df <- data.frame(
  Dim1 = ca_full_coord[,1],
  Dim2 = ca_full_coord[,2],
  Name = rownames(ca_full_coord),
  Cluster = ca_cluster
)

# --- 2. グラフ作成 (ggrepel適用版) ---
p_ca_repel <- ggplot(ca_df, aes(x = Dim1, y = Dim2, color = Cluster)) +
  # 原点を通る補助線
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray85") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray85") +
  # 点のプロット
  geom_point(size = 3.5, alpha = 0.8) +
  # ggrepelによるラベル描画
  geom_text_repel(aes(label = Name), 
                  family = "HiraKakuProN-W3", 
                  fontface = "bold",
                  box.padding = 0.5,      # ラベル周りの余白
                  point.padding = 0.3,    # 点とラベルの間の余白
                  segment.color = "gray50", # ラベルから点へ引く線の色
                  size = 4,
                  show.legend = FALSE) +
  # スケール・色の設定
  scale_color_brewer(palette = "Set1") +
  # 重要:縦横比を1:1に固定
  coord_fixed(ratio = 1) +
  # タイトルとAONF形式のキャプション設定
  labs(title = "福岡11区:対応分析による得票構造の可視化", 
       subtitle = "衆院選2026年福岡11区",
       x = paste0("Dimension 1 (", round(ca_res$eig[1, 2], 1), "%)"), 
       y = paste0("Dimension 2 (", round(ca_res$eig[2, 2], 1), "%)"), 
       color = "Cluster",
       caption = AONF_CAPTION) +
  # AONF標準テーマ
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom",
        plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2))

# グラフの表示
print(p_ca_repel)

対応分析のみ(2024年データ)

library(readr)
library(ggplot2)
library(FactoMineR)
library(ggrepel)
library(dplyr)

# --- 1. 定数の定義 (AONF format) ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

# --- 2. データの準備 ---
data <- read_csv("data11ku_PC.csv")
## New names:
## Rows: 15 Columns: 14
## ── Column specification
## ────────────────────────────────────────────────────────
## Delimiter: "," chr (2): ...1, Var.1 dbl (12): JCP, RS, CDP, DPP, JIP, SDP, LDP,
## NKP, SAN, Shiki, Takeda, Murakami
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...1`
voting_data <- as.data.frame(data[,-1])
rownames(voting_data) <- data[[1]]
# 数値データのみを抽出
voting_numeric <- voting_data[, 2:ncol(voting_data)]

# --- 3. 対応分析 (CA) とクラスタリング ---
ca_res <- CA(voting_numeric, graph = FALSE)

# 列変数(政党・候補者等)の座標を取得
ca_full_coord <- ca_res$col$coord 
# 階層的クラスター分析 (Ward法、3グループ)
ca_hc <- hclust(dist(ca_full_coord), method = "ward.D2")
ca_cluster <- factor(cutree(ca_hc, k = 3))

# 可視化用データフレーム
ca_df <- data.frame(
  Dim1 = ca_full_coord[,1],
  Dim2 = ca_full_coord[,2],
  Name = rownames(ca_full_coord),
  Cluster = ca_cluster
)

# --- 4. 可視化 (CA + ggrepel + AONF format) ---
p_ca_clean <- ggplot(ca_df, aes(x = Dim1, y = Dim2, color = Cluster)) +
  # 原点を通る補助線
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray85") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray85") +
  # データのプロット
  geom_point(size = 3.5, alpha = 0.8) +
  # ggrepelによるラベル描画
  geom_text_repel(aes(label = Name), 
                  family = "HiraKakuProN-W3", 
                  fontface = "bold",
                  box.padding = 0.5, 
                  point.padding = 0.3,
                  segment.color = "gray50",
                  show.legend = FALSE) +
  # スケール・色の設定
  scale_color_brewer(palette = "Set1") +
  # 重要:縦横比を1:1に固定
  coord_fixed(ratio = 1) +
  # タイトルとAONF形式のキャプション設定
 labs(title = "福岡11区:対応分析による得票構造の可視化", subtitle = "衆院選2024年福岡11区",
       x = paste0("Dimension 1 (", round(ca_res$eig[1, 2], 1), "%)"), 
       y = paste0("Dimension 2 (", round(ca_res$eig[2, 2], 1), "%)"), 
       color = "Cluster",
       caption = AONF_CAPTION) +
  # AONF標準テーマ
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom",
        plot.caption = element_text(size = 8, hjust = 1, color = "gray30", lineheight = 1.2))

# --- 5. 実行 ---
print(p_ca_clean)

キャンプのswing

# --- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ca)
library(ggplot2)
library(ggrepel)
library(dplyr)
library(tidyr)

# 1. データの読み込み
d24 <- read.csv("data11ku_PC_fixed.csv")
d26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 陣営(キャンプ)の完全統合
# 2024年
df24_all_camp <- d24 %>%
  mutate(
    自民キャンプ = LDP + Takeda,
    中道キャンプ = CDP + NKP,
    維新キャンプ = JIP + Murakami,  # ← ここで統合
    社民キャンプ = SDP + Shiki,
    参政キャンプ = SAN,
    民主 = DPP, 共産 = JCP, れいわ = RS
  ) %>%
  select(Municipality = 市町村, 自民キャンプ, 中道キャンプ, 維新キャンプ, 
         社民キャンプ, 参政キャンプ, 民主, 共産, れいわ) %>%
  mutate(Year = "2024")

# 2026年
df26_all_camp <- d26 %>%
  mutate(
    自民キャンプ = 自民党 + Takeda,
    中道キャンプ = 中道 + Tsuji,
    維新キャンプ = 維新 + Murakami, # ← ここで統合
    社民キャンプ = 社民党 + Shiki,
    参政キャンプ = 参政 + Inoue,
    民主 = 民主党, 共産 = 共産党,
    保守党 = 保守党, ゆうこく連合 = ゆうこく連合, みらい = みらい
  ) %>%
  select(Municipality, 自民キャンプ, 中道キャンプ, 維新キャンプ, 
         社民キャンプ, 参政キャンプ, 民主, 共産, れいわ, 
         保守党, ゆうこく連合, みらい) %>%
  mutate(Year = "2026")

# 3. 共通行列の作成とCA実行
combined <- bind_rows(df24_all_camp, df26_all_camp) %>% replace(is.na(.), 0)
row_labels <- paste0(combined$Municipality, "_", combined$Year)
counts_matrix <- combined %>% select(-Municipality, -Year)
rownames(counts_matrix) <- row_labels

res_ca <- ca(counts_matrix)
sv_sqrt <- diag(sqrt(res_ca$sv))
rows_coord <- as.data.frame(res_ca$rowcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])
cols_coord <- as.data.frame(res_ca$colcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])

colnames(rows_coord) <- c("Dim1", "Dim2")
rows_coord$FullName <- rownames(counts_matrix)
rows_coord <- rows_coord %>% separate(FullName, into = c("City", "Year"), sep = "_")

colnames(cols_coord) <- c("Dim1", "Dim2")
cols_coord$Name <- colnames(counts_matrix)

# 4. スイングデータの抽出
swing_data <- rows_coord %>%
  pivot_wider(names_from = Year, values_from = c(Dim1, Dim2))

# 5. 可視化 (AONF標準形式)
ggplot() +
  geom_segment(data = swing_data, 
               aes(x = Dim1_2024, y = Dim2_2024, xend = Dim1_2026, yend = Dim2_2026),
               arrow = arrow(length = unit(0.2, "cm")), color = "blue", alpha = 0.4) +
  geom_point(data = cols_coord, aes(x = Dim1, y = Dim2), color = "red", size = 3.5) +
  geom_text_repel(data = cols_coord, aes(x = Dim1, y = Dim2, label = Name), 
                  color = "red", size = 4, fontface = "bold", family="HiraKakuProN-W3") +
  geom_text_repel(data = rows_coord %>% filter(Year == "2026"), 
                  aes(x = Dim1, y = Dim2, label = City), 
                  color = "blue", size = 2.8, alpha = 0.7, family="HiraKakuProN-W3") +
  coord_fixed() +
  theme_minimal(base_family="HiraKakuProN-W3") +
  theme(legend.position = "bottom", plot.caption = element_text(size = 8, color = "gray30")) +
  labs(title = "Fukuoka 11th District: 2024-2026 Full-Camp Swing",
       subtitle = "All major forces aggregated: (Candidate + Party) for true structural comparison",
       x = paste0("Dimension 1 (", round((res_ca$sv[1]^2/sum(res_ca$sv^2))*100, 1), "%)"),
       y = paste0("Dimension 2 (", round((res_ca$sv[2]^2/sum(res_ca$sv^2))*100, 1), "%)"),
       caption = AONF_CAPTION)

政党と候補者の分離版

# --- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ca)
library(dplyr)
library(tidyr)

# 1. データの読み込み
d24 <- read.csv("data11ku_PC_fixed.csv")
d26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 候補者と政党を分離したまま名寄せ
# 2024年 (立憲+公明を「中道」とする)
df24_sep <- d24 %>%
  mutate(中道 = CDP + NKP) %>%
  select(Municipality = 市町村, 自民 = LDP, 維新 = JIP, 民主 = DPP, 
         社民 = SDP, 共産 = JCP, れいわ = RS, 参政 = SAN, 
         中道, Takeda, Shiki, Murakami) %>%
  mutate(Year = "2024")

# 2026年 (候補者と政党を別々に保持)
df26_sep <- d26 %>%
  select(Municipality, 自民 = 自民党, 維新, 民主 = 民主党, 
         社民 = 社民党, 共産 = 共産党, れいわ, 参政, 
         中道, Takeda, Shiki, Murakami, Tsuji, Inoue) %>%
  mutate(Year = "2026")

# 共通行列の作成
combined_sep <- bind_rows(df24_sep, df26_sep) %>% replace(is.na(.), 0)
row_labels <- paste0(combined_sep$Municipality, "_", combined_sep$Year)
counts_matrix <- combined_sep %>% select(-Municipality, -Year)
rownames(counts_matrix) <- row_labels

# 3. 対応分析 (CA)
res_ca_sep <- ca(counts_matrix)

# 4. 座標(列=政党・候補者)の抽出
sv_sqrt <- diag(sqrt(res_ca_sep$sv))
cols_coord <- as.data.frame(res_ca_sep$colcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])

# --- 列名の割り当て
colnames(cols_coord) <- c("Dim1", "Dim2")
# ------------------------------------

cols_coord$Name <- colnames(counts_matrix)

# 5. 座標値を表示(Dim1で昇順ソート)
print("--- 候補者・政党 分離版 Dim1座標 (右ほど保守/地域回帰傾向) ---")
## [1] "--- 候補者・政党 分離版 Dim1座標 (右ほど保守/地域回帰傾向) ---"
print(cols_coord %>% select(Name, Dim1) %>% arrange(Dim1))
##              Name        Dim1
## Shiki       Shiki -0.91726650
## れいわ     れいわ -0.74299085
## 中道         中道 -0.48117766
## 社民         社民 -0.39978629
## 共産         共産 -0.32430642
## Murakami Murakami -0.29669661
## 維新         維新 -0.07824198
## 民主         民主 -0.03956648
## Takeda     Takeda  0.05465939
## 自民         自民  0.41192466
## 参政         参政  0.72341776
## Tsuji       Tsuji  1.75627578
## Inoue       Inoue  1.78939222
# --- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ca)
library(ggplot2)
library(ggrepel)
library(dplyr)
library(tidyr)

# 1. データの読み込み
d24 <- read.csv("data11ku_PC_fixed.csv")
d26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 候補者と政党を「分離」したまま名寄せ
df24_sep <- d24 %>%
  mutate(中道 = CDP + NKP) %>%
  select(Municipality = 市町村, 自民党 = LDP, 維新 = JIP, 民主党 = DPP, 
         社民党 = SDP, 共産党 = JCP, れいわ = RS, 参政 = SAN, 
         中道, Takeda, Shiki, Murakami) %>%
  mutate(Year = "2024")

df26_sep <- d26 %>%
  select(Municipality, 自民党, 維新, 民主党, 
         社民党, 共産党, れいわ, 参政, 
         中道, Takeda, Shiki, Murakami, Tsuji, Inoue) %>%
  mutate(Year = "2026")

# 共通行列の作成
combined_sep <- bind_rows(df24_sep, df26_sep) %>% replace(is.na(.), 0)
row_labels <- paste0(combined_sep$Municipality, "_", combined_sep$Year)
counts_matrix <- combined_sep %>% select(-Municipality, -Year)
rownames(counts_matrix) <- row_labels

# 3. 対応分析 (CA)
res_ca_sep <- ca(counts_matrix)
sv_sqrt <- diag(sqrt(res_ca_sep$sv))
rows_coord <- as.data.frame(res_ca_sep$rowcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])
cols_coord <- as.data.frame(res_ca_sep$colcoord[, 1:2] %*% sv_sqrt[1:2, 1:2])

colnames(rows_coord) <- c("Dim1", "Dim2")
rows_coord$FullName <- rownames(counts_matrix)
rows_coord <- rows_coord %>% separate(FullName, into = c("City", "Year"), sep = "_")

colnames(cols_coord) <- c("Dim1", "Dim2")
cols_coord$Name <- colnames(counts_matrix)

# 4. 可視化
ggplot() +
  # 2024 -> 2026 のスイング
  geom_segment(data = rows_coord %>% pivot_wider(names_from = Year, values_from = c(Dim1, Dim2)),
               aes(x = Dim1_2024, y = Dim2_2024, xend = Dim1_2026, yend = Dim2_2026),
               arrow = arrow(length = unit(0.2, "cm")), color = "blue", alpha = 0.2) +
  # 政党・候補者の点
  geom_point(data = cols_coord, aes(x = Dim1, y = Dim2), color = "red", size = 3) +
  geom_text_repel(data = cols_coord, aes(x = Dim1, y = Dim2, label = Name), 
                  color = "red", size = 3.5, fontface = "bold", family="HiraKakuProN-W3") +
  # 2026年の自治体名
  geom_text(data = rows_coord %>% filter(Year == "2026"), 
            aes(x = Dim1, y = Dim2, label = City), 
            color = "blue", size = 2.5, alpha = 0.5, family="HiraKakuProN-W3") +
  theme_minimal(base_family="HiraKakuProN-W3") +
  theme(legend.position = "bottom", plot.caption = element_text(size = 8)) +
  labs(title = "Fukuoka 11th District: 2024-2026 Split Analysis",
       subtitle = "Separated: 'Tsuji' (Candidate) and '中道' (Party) shows huge strategic gap",
       caption = AONF_CAPTION)

2.2 最大の動員力

# --- AONF定数の定義 (Saved Informationに基づく) ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

#####################################
### 最大動員力(Mobilization Power)分析 - 軸調整版
#####################################

library(ggplot2)
library(dplyr)
library(tidyr)

# 1. データの読み込み
df26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 陣営(キャンプ)ごとの「候補者票」と「政党票」の整理
camp_data <- df26 %>%
  summarise(
    自民_Candidate = sum(Takeda), 自民_Party = sum(自民党),
    中道_Candidate = sum(Tsuji),  中道_Party = sum(中道),
    維新_Candidate = sum(Murakami), 維新_Party = sum(維新),
    参政_Candidate = sum(Inoue),  参政_Party = sum(参政),
    社民_Candidate = sum(Shiki),  社民_Party = sum(社民党)
  ) %>%
  pivot_longer(everything(), names_to = c("Camp", "Type"), names_sep = "_", values_to = "Votes")

# 3. 可視化:軸の範囲を15%拡張して数字の欠けを防止
ggplot(camp_data, aes(x = reorder(Camp, -Votes, sum), y = Votes, fill = Type)) +
  geom_bar(stat = "identity", position = "stack", width = 0.7) +
  # 合計値(最大動員力)を表示
  stat_summary(fun = sum, aes(label = scales::comma(after_stat(y)), group = Camp), 
               geom = "text", vjust = -0.8, size = 3.5, fontface = "bold") +
  # 軸の拡張設定(上方向に15%の余裕を持たせる)
  scale_y_continuous(labels = scales::comma, expand = expansion(mult = c(0, 0.15))) +
  scale_fill_manual(values = c("Candidate" = "#ff7f0e", "Party" = "#1f77b4"),
                    labels = c("Candidate" = "候補者票 (個人力)", "Party" = "政党票 (組織力)")) +
  # AONF標準テーマ (Saved Informationに基づく)
  theme_minimal(base_family="HiraKakuProN-W3") +
  theme(legend.position = "bottom", 
        plot.caption = element_text(size = 8, color = "gray30", hjust = 1)) +
  labs(title = "福岡11区 2026:陣営別「最大動員力」の構造",
       subtitle = "Candidate票とParty票の合算:陣営が有権者にリーチした延べ総数",
       x = "陣営 (Camp)", y = "総得票(延べ数)", fill = "票の内訳",
       caption = AONF_CAPTION)

2.3 得票転移

# --- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

#####################################
### 得票転移(Vote Transfer)推計分析
#####################################

library(ggplot2)
library(dplyr)
library(tidyr)

# 1. データの読み込み
d24 <- read.csv("data11ku_PC_fixed.csv")
d26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 前処理:得票率(Share)の算出
# 2024年の「中道(立憲+公明)」の合計得票率を算出
d24_prep <- d24 %>%
  mutate(Total_24 = CDP + NKP + LDP + JIP + DPP + SDP + JCP + RS + SAN,
         Chudo_Share_24 = (CDP + NKP) / Total_24) %>%
  select(Municipality = 市町村, Chudo_Share_24)

# 2026年の主要候補者の得票率を算出
d26_prep <- d26 %>%
  mutate(Total_26 = Tsuji + Takeda + Shiki + Inoue + Murakami + 
           れいわ + 保守党 + 自民党 + 中道 + ゆうこく連合 + みらい + 
           社民党 + 維新 + 参政 + 民主党 + 共産党) %>%
  mutate(Tsuji_S = Tsuji / Total_26,
         Murakami_S = Murakami / Total_26,
         Takeda_S = Takeda / Total_26,
         Inoue_S = Inoue / Total_26) %>%
  select(Municipality, Tsuji_S, Murakami_S, Takeda_S, Inoue_S)

# データの結合
transfer_df <- inner_join(d24_prep, d26_prep, by = "Municipality")

# 3. グッドマン回帰による転移係数の算出
# 「2024年中道票」が「2026年各候補」にどれだけ寄与したかを回帰係数(Slope)で推定
models <- list(
  Tsuji = lm(Tsuji_S ~ Chudo_Share_24, data = transfer_df),
  Murakami = lm(Murakami_S ~ Chudo_Share_24, data = transfer_df),
  Takeda = lm(Takeda_S ~ Chudo_Share_24, data = transfer_df),
  Inoue = lm(Inoue_S ~ Chudo_Share_24, data = transfer_df)
)

# 係数の抽出
transfer_rates <- data.frame(
  Candidate = names(models),
  Rate = sapply(models, function(m) coef(m)[2]) # 回帰係数(傾き)
)

# 4. 可視化:2024年中道支持層の「吸着度」
ggplot(transfer_rates, aes(x = reorder(Candidate, -Rate), y = Rate, fill = Candidate)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_hline(yintercept = 0, color = "gray50") +
  theme_minimal(base_family="HiraKakuProN-W3") +
  theme(legend.position = "none",
        plot.caption = element_text(size = 8, color = "gray30", hjust = 1)) +
  labs(title = "2024年「中道支持層」はどこへ流れたか(推計)",
       subtitle = "2024年立憲・公明得票率との相関係数に基づく支持の継承度",
       x = "2026年 候補者", y = "支持継承の強さ (Regression Coefficient)",
       caption = AONF_CAPTION)

4つのグラフ

# --- AONF定数の定義 (Saved Informationに基づく) ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)
library(dplyr)
library(tidyr)
library(ggrepel)

# 1. データの読み込み
d24 <- read.csv("data11ku_PC_fixed.csv")
d26 <- read.csv("fukuoka11ku2026_merged_a.csv")

# 2. 得票率の算出
d24_prep <- d24 %>%
  mutate(Total_24 = CDP + NKP + LDP + JIP + DPP + SDP + JCP + RS + SAN,
         Chudo_Share_24 = (CDP + NKP) / Total_24) %>%
  select(Municipality = 市町村, Chudo_Share_24)

d26_prep <- d26 %>%
  mutate(Total_26 = Tsuji + Takeda + Shiki + Inoue + Murakami + 
           れいわ + 保守党 + 自民党 + 中道 + ゆうこく連合 + みらい + 
           社民党 + 維新 + 参政 + 民主党 + 共産党) %>%
  mutate(Tsuji = Tsuji / Total_26,
         Murakami = Murakami / Total_26,
         Takeda = Takeda / Total_26,
         Inoue = Inoue / Total_26) %>%
  select(Municipality, Tsuji, Murakami, Takeda, Inoue)

# データの結合と縦長形式への変換(Facet用)
plot_df <- inner_join(d24_prep, d26_prep, by = "Municipality") %>%
  pivot_longer(cols = c(Tsuji, Murakami, Takeda, Inoue), 
               names_to = "Candidate", values_to = "Share_26")

# 3. 4つの散布図の可視化
ggplot(plot_df, aes(x = Chudo_Share_24, y = Share_26)) +
  # 回帰直線の描画
  geom_smooth(method = "lm", se = FALSE, color = "gray60", linetype = "dashed", linewidth = 0.5) +
  # 自治体ポイント
  geom_point(aes(color = Candidate), size = 2.5, alpha = 0.8) +
  # 自治体名のラベル(Saved Informationに基づき日本語フォント指定)
  geom_text_repel(aes(label = Municipality), size = 2.5, family = "HiraKakuProN-W3") +
  # 候補者ごとにグラフを分割
  facet_wrap(~ Candidate, scales = "free_y") +
  # AONF標準テーマ (Saved Informationに基づく)
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "none",
        plot.caption = element_text(size = 8, color = "gray30", hjust = 1),
        strip.background = element_rect(fill = "gray95", color = "white"),
        strip.text = element_text(face = "bold")) +
  labs(title = "2024年「中道支持層」の流動性:自治体別散布図",
       subtitle = "X軸:2024年立憲・公明得票率 / Y軸:2026年各候補者得票率",
       x = "2024年 中道票シェア(立憲+公明)",
       y = "2026年 候補者個人得票率",
       caption = AONF_CAPTION)
## `geom_smooth()` using formula = 'y ~ x'

3. 政治的影響力(ハブの強さ)と実得票数の相関分析

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)
library(ggrepel)

# 資料29Pの市町村別得票数から算出した正確な合計値
df_exact <- data.frame(
  Name = c("自民党", "武田", "ゆうこく連合", "中道", "Tsuji", "Inoue", 
           "民主党", "参政", "保守党", "みらい", "維新", "Murakami", "共産党", "Shiki"),
  HubStrength = c(2.5, 2.5, 3.0, 2.5, 1.0, 1.5, 2.0, 1.5, 1.5, 1.5, 1.0, 1.0, 1.0, 1.0),
  TotalVotes = c(54433, 62419, 1861, 25744, 19011, 10070, 8540, 10691, 2993, 5690, 15485, 43002, 4746, 5187)
)

# 可視化の実行
ggplot(df_exact, aes(x = HubStrength, y = TotalVotes, label = Name)) +
  # 点の描画(サイズを得票数に比例)
  geom_point(aes(size = TotalVotes), color = "steelblue", alpha = 0.7) +
  # ラベルの重なり防止
  geom_text_repel(family = "HiraKakuProN-W3", box.padding = 0.6, max.overlaps = Inf) +
  # サイズの範囲調整
  scale_size_continuous(range = c(3, 15), guide = "none") + 
  # 縦軸の範囲設定(円が欠けないように75,000まで拡張)
  scale_y_continuous(limits = c(0, 75000), labels = scales::comma) +
  # AONF標準設定
  labs(
    title = "Hub Strength vs. Actual Votes (Fukuoka 11th District 2026)",
    subtitle = "政治的影響力(ハブの強さ)と実得票数の相関分析",
    x = "ハブの強さ (Hub Strength / 次数)",
    y = "実得票数 (Total Votes)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, hjust = 1, color = "gray30")
  )

4. COR(候補者超過達成比率)

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

df_cor_fixed <- data.frame(
  Candidate = c("Murakami", "Shiki", "Takeda", "Inoue", "Tsuji"),
  COR = c(2.78, 1.18, 1.15, 0.94, 0.74)
)

# 可視化
ggplot(df_cor_fixed, aes(x = reorder(Candidate, -COR), y = COR, fill = COR > 1)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") +
  geom_text(aes(label = sprintf("%.2f", COR)), vjust = -0.5, family = "HiraKakuProN-W3") +
  # 軸の拡張設定(上方向に15%の余裕を持たせる)
  scale_y_continuous(labels = scales::comma, expand = expansion(mult = c(0, 0.15))) +
  scale_fill_manual(values = c("TRUE" = "steelblue", "FALSE" = "indianred")) +
  labs(
    title = "Candidate Overperformance Ratio (Fukuoka 11th District 2026)",
    subtitle = "個人得票力指数(COR)",
    x = "候補者名",
    y = "COR (候補者得票 / 政党比例得票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 自治体別CORデータ(資料29Pに基づく)
df_tsuji_cor <- data.frame(
  City = c("苅田町", "行橋市", "田川市", "上毛町", "吉富町", "みやこ町", 
           "豊前市", "福智町", "糸田町", "添田町", "築上町", "香春町", "川崎町", "赤村", "大任町"),
  COR = c(0.88, 0.82, 0.79, 0.76, 0.75, 0.75, 0.75, 0.70, 0.66, 0.63, 0.62, 0.59, 0.57, 0.48, 0.38)
)

# 可視化
ggplot(df_tsuji_cor, aes(x = reorder(City, COR), y = COR)) +
  geom_bar(stat = "identity", fill = "indianred", alpha = 0.8) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "gray50") +
  geom_hline(yintercept = 0.74, linetype = "dotted", color = "blue") + # 全体平均
  geom_text(aes(label = sprintf("%.2f", COR)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 1.1)) +
  labs(
    title = "Municipal COR for Candidate Tsuji (Fukuoka 11th District 2026)",
    subtitle = "辻候補の自治体別COR:青い点線は全体平均(0.74)",
    x = "自治体名",
    y = "COR (個人票 / 政党票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 資料29Pの正確な集計値に基づくデータ
df_murakami_cor <- data.frame(
  City = c("吉富町", "赤村", "上毛町", "苅田町", "行橋市", "築上町", "田川市", 
           "川崎町", "香春町", "福智町", "みやこ町", "豊前市", "添田町", "糸田町", "大任町"),
  COR = c(3.35, 3.07, 2.93, 2.84, 2.81, 2.80, 2.78, 2.73, 2.71, 2.70, 2.69, 2.69, 2.63, 2.62, 2.34)
)

# 可視化:タイトルに \n を入れて改行
ggplot(df_murakami_cor, aes(x = reorder(City, COR), y = COR)) +
  geom_bar(stat = "identity", fill = "steelblue", alpha = 0.8) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") + 
  geom_hline(yintercept = 2.78, linetype = "dotted", color = "blue") + 
  geom_text(aes(label = sprintf("%.2f", COR)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 4.0)) +
  labs(
    # \n を使ってタイトルを2行に分割
    title = "Municipal COR for Candidate Murakami\n(Fukuoka 11th District 2026)",
    subtitle = "村上候補の自治体別COR:青い点線は全体平均(2.78)",
    x = "自治体名",
    y = "COR (個人票 / 政党票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2), # 行間の調整
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

2候補の比較

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)
library(tidyr)
library(dplyr)

# 資料29Pに基づく正確なCORデータ
df_compare <- data.frame(
  City = c("吉富町", "赤村", "上毛町", "苅田町", "行橋市", "築上町", "田川市", 
           "川崎町", "香春町", "福智町", "みやこ町", "豊前市", "添田町", "糸田町", "大任町"),
  Murakami = c(3.35, 3.07, 2.93, 2.84, 2.81, 2.80, 2.78, 2.73, 2.71, 2.70, 2.69, 2.69, 2.63, 2.62, 2.34),
  Tsuji = c(0.75, 0.48, 0.76, 0.88, 0.82, 0.62, 0.79, 0.57, 0.59, 0.70, 0.75, 0.75, 0.63, 0.66, 0.38)
)

# 比較用にデータをロング形式に変換
df_long <- df_compare %>%
  pivot_longer(cols = c(Murakami, Tsuji), names_to = "Candidate", values_to = "COR")

# 可視化
ggplot(df_long, aes(x = reorder(City, COR), y = COR, fill = Candidate)) +
  # サイド・バイ・サイドの棒グラフ
  geom_bar(stat = "identity", position = position_dodge(width = 0.7), width = 0.6) +
  # 政党票ライン (COR=1.0)
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red", alpha = 0.5) +
  # 数値ラベル
  geom_text(aes(label = sprintf("%.2f", COR)), 
            position = position_dodge(width = 0.7), 
            hjust = -0.2, size = 2.5, family = "HiraKakuProN-W3") +
  # 軸を反転させて読みやすく
  coord_flip() +
  scale_y_continuous(limits = c(0, 4.2)) +
  scale_fill_manual(values = c("Murakami" = "steelblue", "Tsuji" = "indianred"),
                    labels = c("Murakami" = "村上候補", "Tsuji" = "辻候補")) +
  labs(
    title = "Municipal COR Comparison: Murakami vs. Tsuji\n(Fukuoka 11th District 2026)",
    subtitle = "自治体別個人得票力指数の比較:赤の破線(1.0)は政党票相当",
    x = "自治体名",
    y = "COR (個人得票 / 政党比例票)",
    fill = "候補者名",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

武田候補(当選者)のCOR

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 武田候補の自治体別CORデータ(資料29Pに基づく正確な算出値)
df_takeda_cor <- data.frame(
  City = c("大任町", "糸田町", "赤村", "川崎町", "福智町", "香春町", "添田町", 
           "田川市", "吉富町", "豊前市", "上毛町", "みやこ町", "苅田町", "行橋市", "築上町"),
  COR = c(1.42, 1.39, 1.36, 1.35, 1.34, 1.31, 1.23, 1.18, 1.17, 1.14, 1.14, 1.12, 1.05, 1.04, 0.94)
)

# 可視化
ggplot(df_takeda_cor, aes(x = reorder(City, COR), y = COR)) +
  geom_bar(stat = "identity", fill = "steelblue", alpha = 0.8) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") + # 政党票ライン
  geom_hline(yintercept = 1.15, linetype = "dotted", color = "blue") + # 全体平均
  geom_text(aes(label = sprintf("%.2f", COR)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 1.8)) +
  labs(
    title = "Municipal COR for Candidate Takeda\n(Fukuoka 11th District 2026)",
    subtitle = "武田候補の自治体別COR:青い点線は全体平均(1.15)",
    x = "自治体名",
    y = "COR (個人票 / 政党票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

井上候補のCOR

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 井上候補の自治体別CORデータ
df_inoue_cor <- data.frame(
  City = c("苅田町", "上毛町", "行橋市", "糸田町", "吉富町", "福智町", "みやこ町", 
           "香春町", "田川市", "川崎町", "豊前市", "添田町", "築上町", "大任町", "赤村"),
  COR = c(1.09, 1.04, 1.02, 0.97, 0.94, 0.91, 0.91, 0.89, 0.89, 0.87, 0.86, 0.83, 0.74, 0.67, 0.65)
)

# 可視化
ggplot(df_inoue_cor, aes(x = reorder(City, COR), y = COR, fill = COR > 1)) +
  geom_bar(stat = "identity", width = 0.7, alpha = 0.8) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") + 
  geom_hline(yintercept = 0.94, linetype = "dotted", color = "blue") + # 全体平均
  geom_text(aes(label = sprintf("%.2f", COR)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 1.4)) +
  scale_fill_manual(values = c("TRUE" = "indianred", "FALSE" = "indianred")) +
  labs(
    title = "Municipal COR for Candidate Inoue\n(Fukuoka 11th District 2026)",
    subtitle = "井上候補の自治体別COR:青い点線は全体平均(0.94)",
    x = "自治体名",
    y = "COR (個人得票 / 政党比例票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "none",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

志岐候補のCOR

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 志岐候補の自治体別CORデータ(CSV集計値に基づく正確な算出値)
df_shiki_cor <- data.frame(
  City = c("苅田町", "吉富町", "川崎町", "田川市", "行橋市", "糸田町", "福智町", 
           "添田町", "豊前市", "みやこ町", "上毛町", "香春町", "赤村", "築上町", "大任町"),
  COR = c(1.53, 1.49, 1.31, 1.29, 1.24, 1.14, 1.10, 1.10, 1.07, 1.03, 1.01, 0.96, 0.89, 0.89, 0.84)
)

# 可視化:主要カラーに鮭色(社民党イメージに近い暖色)を採用
ggplot(df_shiki_cor, aes(x = reorder(City, COR), y = COR, fill = COR > 1)) +
  geom_bar(stat = "identity", width = 0.7, alpha = 0.8) +
  geom_hline(yintercept = 1.0, linetype = "dashed", color = "red") + 
  geom_hline(yintercept = 1.18, linetype = "dotted", color = "blue") + # 全体平均
  geom_text(aes(label = sprintf("%.2f", COR)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 1.8)) +
  scale_fill_manual(values = c("TRUE" = "steelblue", "FALSE" = "steelblue")) +
  labs(
    title = "Municipal COR for Candidate Shiki\n(Fukuoka 11th District 2026)",
    subtitle = "志岐候補の自治体別COR:青い点線は全体平均(1.18)",
    x = "自治体名",
    y = "COR (個人得票 / 政党比例票)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "none",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

5. 政党得票率(福岡11区全体)

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 福岡11区全体での政党得票率データ
df_party_total <- data.frame(
  Party = c("自民党", "中道", "維新", "参政", "民主党", "みらい", 
            "共産党", "れいわ", "社民党", "保守党", "ゆうこく連合"),
  Rate = c(39.10, 18.49, 11.12, 7.68, 6.12, 4.09, 3.41, 3.33, 3.16, 2.15, 1.34)
)

# 可視化
ggplot(df_party_total, aes(x = reorder(Party, Rate), y = Rate, fill = Party)) +
  geom_bar(stat = "identity", alpha = 0.8) +
  geom_text(aes(label = sprintf("%.2f%%", Rate)), hjust = -0.1, size = 3.5, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 45), breaks = seq(0, 45, 10)) +
  # 視認性向上のためのカラーパレット(任意で調整可能)
  scale_fill_manual(values = c(
    "自民党" = "dodgerblue4", "中道" = "indianred", "維新" = "turquoise4", 
    "参政" = "#E69F00", "民主党" = "darkcyan", "みらい" = "gray50", 
    "共産党" = "firebrick", "れいわ" = "deeppink3", "社民党" = "salmon", 
    "保守党" = "darkblue", "ゆうこく連合" = "darkgreen"
  )) +
  labs(
    title = "PR Vote Share by Party (Fukuoka 11th District Total 2026)",
    subtitle = "各政党の比例代表得票率(福岡11区全体:有効投票数 139,208票)",
    x = "政党名",
    y = "得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(size = 14, face = "bold"),
    legend.position = "none", # 棒グラフ自体に色がついているため凡例は省略
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

自民党の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 自民党の自治体別比例得票率データ(正確な算出値)
df_ldp_pr <- data.frame(
  City = c("大任町", "赤村", "上毛町", "築上町", "みやこ町", "添田町", "豊前市", 
           "香春町", "行橋市", "福智町", "川崎町", "吉富町", "苅田町", "田川市", "糸田町"),
  Rate = c(50.53, 44.07, 42.24, 40.93, 40.88, 40.49, 40.20, 40.09, 38.99, 38.69, 38.51, 38.09, 37.70, 36.32, 36.05)
)

# 可視化
ggplot(df_ldp_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) + # 自民党のイメージカラー
  geom_hline(yintercept = 39.1, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.1f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 60), breaks = seq(0, 60, 10)) +
  labs(
    title = "LDP PR Vote Share by Municipality (Fukuoka 11th District 2026)",
    subtitle = "自民党の自治体別比例得票率:赤の破線は全体平均(39.1%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

中道の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 中道の自治体別比例得票率データ
df_chudo_pr <- data.frame(
  City = c("川崎町", "糸田町", "添田町", "香春町", "福智町", "吉富町", "赤村", 
           "田川市", "みやこ町", "大任町", "苅田町", "豊前市", "行橋市", "上毛町", "築上町"),
  Rate = c(25.74, 25.11, 21.25, 20.92, 20.33, 19.28, 18.96, 18.82, 18.63, 18.16, 17.61, 17.13, 16.89, 15.58, 15.07)
)

# 可視化
ggplot(df_chudo_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) + 
  geom_hline(yintercept = 18.5, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.1f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 30), breaks = seq(0, 30, 5)) +
  labs(
    title = "Chudo PR Vote Share by Municipality\n (Fukuoka 11th District 2026)",
    subtitle = "中道改革連合の自治体別比例得票率:赤の破線は全体平均(18.5%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

参政党の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 参政党の自治体別比例得票率データ
df_sanseito <- data.frame(
  City = c("苅田町", "吉富町", "行橋市", "豊前市", "上毛町", "田川市", "福智町", 
           "築上町", "香春町", "みやこ町", "糸田町", "川崎町", "大任町", "添田町", "赤村"),
  Rate = c(9.22, 8.77, 8.17, 7.93, 7.74, 7.59, 7.48, 7.09, 6.80, 6.78, 6.77, 6.26, 6.22, 6.12, 6.00)
)

# 可視化:参政党のイメージカラーに近いオレンジ系(#E69F00)を使用
ggplot(df_sanseito, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) +
  geom_hline(yintercept = 7.68, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.2f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 12), breaks = seq(0, 12, 2)) +
  labs(
    title = "Sanseito PR Vote Share by Municipality \n(Fukuoka 11th District 2026)",
    subtitle = "参政党の自治体別比例得票率:赤の破線は全体平均(7.68%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

維新の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 維新の自治体別比例得票率データ(正確な算出値)
df_ishin_pr <- data.frame(
  City = c("築上町", "行橋市", "みやこ町", "豊前市", "苅田町", "添田町", "田川市", 
           "上毛町", "香春町", "吉富町", "川崎町", "福智町", "糸田町", "赤村", "大任町"),
  Rate = c(16.01, 12.26, 11.83, 11.72, 11.05, 10.92, 10.90, 9.83, 9.45, 8.71, 8.64, 8.59, 8.50, 8.39, 6.93)
)

# 可視化:維新のイメージカラーに近いターコイズ系を採用
ggplot(df_ishin_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) +
  geom_hline(yintercept = 11.1, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.1f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 20), breaks = seq(0, 20, 5)) +
  labs(
    title = "Ishin PR Vote Share by Municipality (Fukuoka 11th District 2026)",
    subtitle = "日本維新の会の自治体別比例得票率:赤の破線は全体平均(11.1%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

国民民主党の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 国民民主党の自治体別比例得票率データ
df_dpp_pr <- data.frame(
  City = c("苅田町", "行橋市", "吉富町", "上毛町", "みやこ町", "田川市", "豊前市", 
           "築上町", "赤村", "福智町", "糸田町", "大任町", "香春町", "添田町", "川崎町"),
  Rate = c(8.16, 7.34, 6.41, 6.00, 5.80, 5.66, 5.43, 5.42, 5.25, 5.20, 5.07, 4.58, 4.58, 4.30, 4.02)
)

# 可視化
ggplot(df_dpp_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) + 
  geom_hline(yintercept = 6.12, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.2f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 10), breaks = seq(0, 10, 2)) +
  labs(
    title = "DPP PR Vote Share by Municipality (Fukuoka 11th District 2026)",
    subtitle = "国民民主党の自治体別比例得票率:赤の破線は全体平均(6.12%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

社民党の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 社民党の自治体別比例得票率データ
df_sdp_pr <- data.frame(
  City = c("赤村", "福智町", "糸田町", "田川市", "香春町", "豊前市", "川崎町", 
           "上毛町", "添田町", "築上町", "みやこ町", "大任町", "行橋市", "吉富町", "苅田町"),
  Rate = c(4.50, 4.47, 4.30, 4.27, 4.11, 3.45, 3.36, 3.18, 3.16, 2.89, 2.88, 2.66, 2.45, 2.39, 2.01)
)

# 可視化
ggplot(df_sdp_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) + 
  geom_hline(yintercept = 3.16, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.2f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 6), breaks = seq(0, 6, 1)) +
  labs(
    title = "SDP PR Vote Share by Municipality (Fukuoka 11th District 2026)",
    subtitle = "社会民主党の自治体別比例得票率:赤の破線は全体平均(3.16%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )

共産党の得票率

#--- AONF定数の定義 ---
AONF_CAPTION <- "Archives from 2026 Onward and Notes for the Future\n2026年以降の記録 | https://ab.cocolog-nifty.com/note/"

library(ggplot2)

# 共産党の自治体別比例得票率データ(正確な算出値)
df_jcp_pr <- data.frame(
  City = c("田川市", "吉富町", "添田町", "福智町", "川崎町", "香春町", "上毛町", 
           "糸田町", "みやこ町", "行橋市", "豊前市", "築上町", "苅田町", "赤村", "大任町"),
  Rate = c(5.23, 5.18, 4.30, 4.07, 4.02, 3.91, 3.39, 3.19, 3.10, 2.81, 2.72, 2.60, 2.52, 2.39, 1.72)
)

# 可視化
ggplot(df_jcp_pr, aes(x = reorder(City, Rate), y = Rate)) +
  geom_bar(stat = "identity", fill = "dodgerblue4", alpha = 0.8) + 
  geom_hline(yintercept = 3.41, linetype = "dashed", color = "red") + # 全体平均
  geom_text(aes(label = sprintf("%.2f%%", Rate)), hjust = -0.2, size = 3, family = "HiraKakuProN-W3") +
  coord_flip() +
  scale_y_continuous(limits = c(0, 7), breaks = seq(0, 7, 1)) +
  labs(
    title = "JCP PR Vote Share by Municipality (Fukuoka 11th District 2026)",
    subtitle = "日本共産党の自治体別比例得票率:赤の破線は全体平均(3.41%)",
    x = "自治体名",
    y = "比例得票率 (%)",
    caption = AONF_CAPTION
  ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(
    plot.title = element_text(lineheight = 1.2),
    legend.position = "bottom",
    plot.caption = element_text(size = 8, color = "gray30", hjust = 1)
  )