---
title: "ドント方式の計算方法"
author: kenji@kenjisato.jp
output:
  html_document: default
  html_notebook: default
---

# 目的¶

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

# 準備

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

```{r, message=FALSE, warging=FALSE}
library(dplyr)
```

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

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

votes = data.frame(party, nvote)
votes
```

改選議席数は 48 である. 

```{r}
nseat = 48
```


# 考え方の確認

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

```{r}
votes %>%
  mutate(divide_by_2 = nvote %/% 2)
```

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

```{r}
votes %>%
  mutate(divide_by_2 = nvote %/% 2) %>%
  mutate(step1 = nvote > max(divide_by_2)) %>%
  select(party, step1)
```

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

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


# ドント方式

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

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

dhondt0
```

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

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

dhondt0 %>% 
  rbind(mutate(temp))
  
```


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


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


```{r}
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行は次のようになる.

```{r}
head(dhondt, 20)
```

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

```{r}
tail(dhondt, 20)
```

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

```{r}
dhondt %>%
  mutate(rank = rank(-value)) %>%
  filter(rank <= nseat) 
```

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

```{r}
dhondt %>%
  mutate(rank = rank(-value)) %>%
  filter(rank <= nseat) %>%
  group_by(party) %>%
  summarize(seats = n()) %>%
  arrange(desc(seats)) %>%
  as.data.frame()
```