衆院選は自民党の圧勝で終わりました。民主党はどうしてここまで惨敗してしまったのでしょうか。小選挙区制に原因があるとも言われています。小選挙区での得票数と議席は以下のようになります。従来から小選挙区制度では2大政党制になるだとか、なんだとか色々なことがいわれているようですがそれって本当なんでしょうか。
その他にも、一票の格差が結果に影響を与えているかもしれません。民主党は都市部で強くて、一票の格差のために不利であるという説もあります。
Ruby を使って簡単に実験してみましょう。
小選挙区での得票数と議席 | ||
得票数 | 議席 | |
自民 | 32518389 | 219 |
民主 | 24804786 | 52 |
公明 | 981105 | 8 |
共産 | 4937375 | 0 |
社民 | 996007 | 1 |
国民 | 432679 | 2 |
日本 | 137172 | 0 |
無所属 | 3240521 | 18 |
300の選挙区の人口はすべて同じだとします。上の得票をランダムに300の小選挙区に割り振っていき、選挙区毎にトップになった政党がその選挙区の議席を獲得するとします。プログラムを速くて簡単なものにするために、各選挙区の人口を実際の1/100として、政党に投票する確率は独立同分布にしています。
voter = {} voter[:jimin] = 32518389 voter[:minshu] = 24804786 voter[:kome] = 981105 voter[:kyosan] = 4937375 voter[:shamin] = 996007 voter[:kokumin]= 432679 voter[:nippon] = 137172 voter[:mushozk]= 3240521 seats = {} voter.each_key{|k| seats[k] = 0} sum = 0 voter.each_value{|v| sum += v} voter_per_zone = sum / (300 * 100) 300.times{ zone = {} voter.each_key{|k| zone[k] = 0} voter_per_zone.times{ vote = rand(sum) + 1 voter.each{|k, v| if vote <= v zone[k] += 1 break else vote -= v end } } seats[zone.sort{|a, b| a[1] <=> b[1]}[-1][0]] += 1 } seats.each{|k, v| puts "%7s" % k + ": %4d" % v }
さて結果は、実際の選挙結果と似たようなものになるでしょうか。それとも、民主党に有利なものになるでしょうか。少し考えてみて下さい。
結果は以下のようになります。
$ ruby vote.rb jimin: 300 nippon: 0 minshu: 0 mushozk: 0 kome: 0 kyosan: 0 shamin: 0 kokumin: 0
驚くべきことに、自民党がすべての小選挙区で議席を獲得してしまうのです。つまり私たちの単純なモデルは現実をうまく説明できないということです。また、最初の問の立て方も間違っていたことが分かります。私たちは「どうして民主党が惨敗したのか」ではなく、「どうして民主党はこんなにも小選挙区で議席を獲得できたか」を考えないといけません。
しかし、有権者が実際にどのように投票しているかを考えるトイモデルとしてはなかなか悪くないでしょう。得票率を色々変えて遊んでみると良いかもしれません。例えば、小選挙区にランダムに各党の支持者が住んでいるこの単純なモデルでは、得票数がかなり拮抗しないと2大政党制にはならないことが分かります。2大政党制はそんなに簡単には実現しないようです。
このようなことを考えていくのが政治学であると僕は理解しています。
Hash#each は遅いのか。
$ cat h_vs_a.rb require 'benchmark' h = {} n = 1000000 n.times{|i| h[i] = nil } a = Array.new(n) Benchmark.bm{|b| b.report do h.each{|k, v| } end b.report do a.each{|e| } end }
$ ruby -v h_vs_a.rb ruby 1.9.0 (2005-09-09) [i686-linux] user system total real 9.250000 0.030000 9.280000 ( 10.004543) 0.330000 0.000000 0.330000 ( 0.337381)
Hash を Array で書き直し。
voter = [ [:jimin, 32518389], [:minshu, 24804786], [:kome, 981105], [:kyosan, 4937375], [:shamin, 996007], [:kokumin, 432679], [:nippon, 137172], [:mushozk, 3240521], ] seats = {} voter.each{|k| seats[k[0]] = 0} sum = 0 voter.each{|v| sum += v[1]} voter_per_zone = sum / (300*100) 300.times{ zone = {} voter.each{|k| zone[k[0]] = 0} voter_per_zone.times{ vote = rand(sum) + 1 voter.each{|k| if vote <= k[1] zone[k[0]] += 1 break else vote -= k[1] end } } seats[zone.sort{|a, b| a[1] <=> b[1]}[-1][0]] += 1 } seats.each{|k, v| puts "%7s" % k + ": %4d" % v }
$ time ruby -v vote.rb > /dev/null 3.33s user 0.01s system 98% cpu 3.401 total $ time ruby -v vote.rb.old > /dev/null 7.78s user 0.01s system 99% cpu 7.827 total $ time ./miniruby -v ../../vote.rb ruby 1.9.0 (2005-08-19) [i686-linux] YARVCore 0.3.1 (rev: 254) [opts: [direct threaded code] [optimize basic operation] [stack caching] [operands unification] [instructions unification] [inline method cache] ] 1.18s user 0.00s system 81% cpu 1.450 total $ time ./miniruby -v ../../vote.rb.bak ruby 1.9.0 (2005-08-19) [i686-linux] YARVCore 0.3.1 (rev: 254) [opts: [direct threaded code] [optimize basic operation] [stack caching] [operands unification] [instructions unification] [inline method cache] ] 7.34s user 0.00s system 96% cpu 7.577 total
yarv だと違いが顕著だ。
独立同分布じゃないバージョン。
voter = [ [:jimin, 32518389], [:minshu, 24804786], [:kome, 981105], [:kyosan, 4937375], [:shamin, 996007], [:kokumin, 432679], [:nippon, 137172], [:mushozk, 3240521], ] voter.each{|e| e[1] /= 100 } seats = {} voter.each{|e| seats[e[0]] = 0} sum = 0 voter.each{|e| sum += e[1]} voter_per_zone = sum / 300 300.times{ zone = {} voter.each{|e| zone[e[0]] = 0} voter_per_zone.times{ vote = rand(sum) + 1 voter.each{|e| if vote <= e[1] zone[e[0]] += 1 e[1] -= 1 break else vote -= e[1] end } sum -= 1 } seats[zone.sort{|a, b| a[1] <=> b[1]}[-1][0]] += 1 } seats.each{|k, v| puts "%7s" % k + ": %4d" % v }
最近のコメント