目的¶

2016年の参議院選挙比例区の実際の投票数を用いてドント方式の計算方法を確認する. 講義では簡単な数値例で説明したが, 規模が大きくなっても同じように計算できる.

準備

必要なパッケージを読み込む.

library(dplyr)

投票数をデータフレームに投入. データは例えば, http://www.asahi.com/senkyo/senkyo2016/kaihyo/C01.html から取得できる.

party = c("自民", "民進", "公明", "共産", "お維新", "社民", "生活",
          "こころ", "改革", "幸福")
nvote = c(20114788, 11750965, 7572960, 6016195, 5153584, 1536238, 1067300,
          734024, 580653, 366815)

votes = data.frame(party, nvote)
votes
##     party    nvote
## 1    自民 20114788
## 2    民進 11750965
## 3    公明  7572960
## 4    共産  6016195
## 5  お維新  5153584
## 6    社民  1536238
## 7    生活  1067300
## 8  こころ   734024
## 9    改革   580653
## 10   幸福   366815

改選議席数は 48 である.

nseat = 48

考え方の確認

R では割り算の商は %/% を使う. 議席数を2で割った商を追加したテーブルを作成してみよう.

votes %>%
  mutate(divide_by_2 = nvote %/% 2)
##     party    nvote divide_by_2
## 1    自民 20114788    10057394
## 2    民進 11750965     5875482
## 3    公明  7572960     3786480
## 4    共産  6016195     3008097
## 5  お維新  5153584     2576792
## 6    社民  1536238      768119
## 7    生活  1067300      533650
## 8  こころ   734024      367012
## 9    改革   580653      290326
## 10   幸福   366815      183407

nvote と書かれた列 (得票数を表す) の中に, nvote2の最大数より大きい数字があれば, 政党は1議席確保できる. nvote2 の最大は 10057394 なので, 自民と民進が1議席を確保できる.

votes %>%
  mutate(divide_by_2 = nvote %/% 2) %>%
  mutate(step1 = nvote > max(divide_by_2)) %>%
  select(party, step1)
##     party step1
## 1    自民  TRUE
## 2    民進  TRUE
## 3    公明 FALSE
## 4    共産 FALSE
## 5  お維新 FALSE
## 6    社民 FALSE
## 7    生活 FALSE
## 8  こころ FALSE
## 9    改革 FALSE
## 10   幸福 FALSE

step2 では, 3 で割った商を計算し, その最大よりも大きい数字が 1 で割った商と 2 で割った商の中にあればその政党が議席を獲得する.

これを順番に実行していけばいいのだが, 議席数が大きくなると大変なので自動化しよう.

ドント方式

自然数で割って, その商を記録していくというのが基本的な考え方である.

dhondt0 = votes %>%
  mutate(divide_by = 1, value = nvote %/% 1) %>%
  select(party, divide_by, value)

dhondt0
##     party divide_by    value
## 1    自民         1 20114788
## 2    民進         1 11750965
## 3    公明         1  7572960
## 4    共産         1  6016195
## 5  お維新         1  5153584
## 6    社民         1  1536238
## 7    生活         1  1067300
## 8  こころ         1   734024
## 9    改革         1   580653
## 10   幸福         1   366815

2 ステップ目は次の様に計算できる.

temp = votes %>%
  mutate(divide_by = 2, value = nvote %/% 2) %>%
  select(party, divide_by, value)

dhondt0 %>% 
  rbind(mutate(temp))
##     party divide_by    value
## 1    自民         1 20114788
## 2    民進         1 11750965
## 3    公明         1  7572960
## 4    共産         1  6016195
## 5  お維新         1  5153584
## 6    社民         1  1536238
## 7    生活         1  1067300
## 8  こころ         1   734024
## 9    改革         1   580653
## 10   幸福         1   366815
## 11   自民         2 10057394
## 12   民進         2  5875482
## 13   公明         2  3786480
## 14   共産         2  3008097
## 15 お維新         2  2576792
## 16   社民         2   768119
## 17   生活         2   533650
## 18 こころ         2   367012
## 19   改革         2   290326
## 20   幸福         2   183407

ステップ数が一番大きくなるのは, 1つの政党がすべての議席を確保するケースであり, この場合は議席数と同じだけステップが必要である. もっと計算量を節約することもできる だろうけど, この程度の無駄は許してしまおう.

同じような計算を繰り返し実行するときには for を使う.

dhondt = data.frame()

for (i in 1:nseat){
  temp = votes %>%
    mutate(divide_by = i, value = nvote %/% i) %>%
    select(party, divide_by, value)
  
  dhondt =
    dhondt %>% rbind(temp)
}

最初の20行は次のようになる.

head(dhondt, 20)
##     party divide_by    value
## 1    自民         1 20114788
## 2    民進         1 11750965
## 3    公明         1  7572960
## 4    共産         1  6016195
## 5  お維新         1  5153584
## 6    社民         1  1536238
## 7    生活         1  1067300
## 8  こころ         1   734024
## 9    改革         1   580653
## 10   幸福         1   366815
## 11   自民         2 10057394
## 12   民進         2  5875482
## 13   公明         2  3786480
## 14   共産         2  3008097
## 15 お維新         2  2576792
## 16   社民         2   768119
## 17   生活         2   533650
## 18 こころ         2   367012
## 19   改革         2   290326
## 20   幸福         2   183407

最後の20行は次のようになっている.

tail(dhondt, 20)
##      party divide_by  value
## 461   自民        47 427974
## 462   民進        47 250020
## 463   公明        47 161126
## 464   共産        47 128004
## 465 お維新        47 109650
## 466   社民        47  32685
## 467   生活        47  22708
## 468 こころ        47  15617
## 469   改革        47  12354
## 470   幸福        47   7804
## 471   自民        48 419058
## 472   民進        48 244811
## 473   公明        48 157770
## 474   共産        48 125337
## 475 お維新        48 107366
## 476   社民        48  32004
## 477   生活        48  22235
## 478 こころ        48  15292
## 479   改革        48  12096
## 480   幸福        48   7641

この大きなデータフレームを value 列に関して大きい順に並べ替えて, 上位48を取り出せばよい.

dhondt %>%
  mutate(rank = rank(-value)) %>%
  filter(rank <= nseat) 
##     party divide_by    value rank
## 1    自民         1 20114788    1
## 2    民進         1 11750965    2
## 3    公明         1  7572960    4
## 4    共産         1  6016195    6
## 5  お維新         1  5153584    8
## 6    社民         1  1536238   31
## 7    生活         1  1067300   47
## 8    自民         2 10057394    3
## 9    民進         2  5875482    7
## 10   公明         2  3786480   12
## 11   共産         2  3008097   14
## 12 お維新         2  2576792   17
## 13   自民         3  6704929    5
## 14   民進         3  3916988   11
## 15   公明         3  2524320   18
## 16   共産         3  2005398   23
## 17 お維新         3  1717861   27
## 18   自民         4  5028697    9
## 19   民進         4  2937741   15
## 20   公明         4  1893240   25
## 21   共産         4  1504048   33
## 22 お維新         4  1288396   38
## 23   自民         5  4022957   10
## 24   民進         5  2350193   20
## 25   公明         5  1514592   32
## 26   共産         5  1203239   41
## 27   自民         6  3352464   13
## 28   民進         6  1958494   24
## 29   公明         6  1262160   39
## 30   自民         7  2873541   16
## 31   民進         7  1678709   28
## 32   公明         7  1081851   45
## 33   自民         8  2514348   19
## 34   民進         8  1468870   34
## 35   自民         9  2234976   21
## 36   民進         9  1305662   37
## 37   自民        10  2011478   22
## 38   民進        10  1175096   43
## 39   自民        11  1828617   26
## 40   民進        11  1068269   46
## 41   自民        12  1676232   29
## 42   自民        13  1547291   30
## 43   自民        14  1436770   35
## 44   自民        15  1340985   36
## 45   自民        16  1257174   40
## 46   自民        17  1183222   42
## 47   自民        18  1117488   44
## 48   自民        19  1058673   48

獲得議席数をカウントするには次のようにすればよい.

dhondt %>%
  mutate(rank = rank(-value)) %>%
  filter(rank <= nseat) %>%
  group_by(party) %>%
  summarize(seats = n()) %>%
  arrange(desc(seats)) %>%
  as.data.frame()
##    party seats
## 1   自民    19
## 2   民進    11
## 3   公明     7
## 4   共産     5
## 5 お維新     4
## 6   生活     1
## 7   社民     1