乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

区間推定

テレビの選挙特番などで
「当確」って出てきますよね。
あれの推定方法などについてです。

解説動画はこちら



テレビ番組によっては開票が行われてすぐに
当確が出てしまったりするケースがあります。

なぜこんなにも早く当確が出るのか
選挙の出口予想の仕組みについて解説します。




出口調査と区間推定の仕組み

選挙の当確を出すためには、それぞれの候補者の得票率を
「だいたい、ここからこの位までの区間に入ってるんじゃないか?」
という区間推定を行なっています。

出口調査で得られた、ある候補者の得票率を p とすると

その区間は次のような計算式で求められます。
スクリーンショット 2025-07-19 15.20.10
ここで必要になってくるのは
出口調査に必要な人数( n ) です。

この区間の誤差を少なくするためには
ある程度の人数が必要で、一般的には無作為に選ばれた
400人ほどが必要になってきます。




区間推定の計算

たとえばある選挙において
候補者 A , B の二人がいるとして
出口調査400人の結果が 
A : 220人
B : 180人
だったとします。

この際のA候補の得票率は

p = 220/400 = 0.55 

全体での得票率の区間の推定は
スクリーンショット 2025-07-19 17.52.43

50.12% ~ 59.88%
となります。

得票率の下限が50%を上回っているため
このまま行けば勝ちが見えてきます。



これが400人中210人だった場合はどうでしょうか

推定得票率: 52.50%
95% 信頼区間: 47.61% ~ 57.39%

これだと得票率の下限が50%を下回っているので
まだ決着がつけられません

もう少しサンプル数が増えた場合はどうなるでしょうか

今度は出口調査で4000人中2100人としてみます。
推定得票率: 52.50%
95% 信頼区間: 50.95% ~ 54.05%

n 調査人数が増えるほど誤差が少なくなり
推定された区間は短くなります。




実際には当確を決めるには

実際には候補者も多く、出口調査のみでは
正確には決まらないことが多いです。


スクリーンショット 2025-07-19 15.52.41

という計算式で当確ラインがもとまります。

これを用いて開票率が進むにつれ
区間推定の下限が当確ラインを超える得票率が獲得できている場合
当確が出せるということになります。






区間推定で当確を計算するコード

候補者が2人
開票が進んで、得票数と全体の数が分かったとします。
関数の引数に入力すると、当確結果がわかります。

最初は全体400 , 獲得210票とします。
import math

def check_win(candidate_votes, total_samples, confidence=0.99):
    if total_samples == 0:
        print("❌ 標本数が0のため、判定できません。")
        return

    # 推定得票率
    phat = candidate_votes / total_samples
    
    # z値の選択
    z = 1.96 if confidence == 0.95 else 2.58 if confidence == 0.99 else 1.64
    
    # 標準誤差と信頼区間
    se = math.sqrt(phat * (1 - phat) / total_samples)
    lower = phat - z * se
    upper = phat + z * se
    
    # 当確ラインの計算
    win_threshold = (1 + math.sqrt(z**2 / (z**2 + total_samples))) / 2

    # 表示
    print(f"推定得票率 : {phat:.2%}")
    print(f"{int(confidence * 100)}% 信頼区間 : {lower:.2%} ~ {upper:.2%}")
    print(f"当確ライン(開票数={total_samples}) : {win_threshold:.2%}")
    
    # 当確判定
    if lower >= win_threshold:
        print("OK : 候補者は『当確』と判断できます。")
    else:
        print("X :  まだ『当確』とは言えません。")

# 使用例
check_win(candidate_votes=210, total_samples=400, confidence=0.95)
推定得票率 : 52.50%
95% 信頼区間 : 47.61% ~ 57.39%
当確ライン(開票数=400) : 54.88%
X :  まだ『当確』とは言えません。

信頼区間の下限は
当確ラインを上回らないので、まだ当確出ません。


2100 , 4000 でやってみると

推定得票率 : 52.50%
95% 信頼区間 : 50.95% ~ 54.05%
当確ライン(開票数=4000) : 51.55%
X :  まだ『当確』とは言えません。

少し、区間が狭まりましたが
信頼区間の下限は
当確ラインを上回らないので、まだ当確出ません。


21000 , 40000 でやってみると

推定得票率 : 52.50%
95% 信頼区間 : 52.01% ~ 52.99%
当確ライン(開票数=40000) : 50.49%
OK : 候補者は『当確』と判断できます。


ようやく上回りました
これでようやく当確が出せるようになります。


出口調査で最初から大差がついている場合は
開票前にすでに決着がついている場合もあるようです。


今回は選挙の当確や
出口調査の仕組みについてでした。

こういった統計を用いた計算なんかも
Pythonを用いると簡単に計算できますね

選挙以外にも使えるので
覚えておくと仕事の幅が広がって便利です。

それでは。


先日、大きな選挙が有りましたね。
何故にすぐ当確が出るのでしょう?

その仕組みを解説してみました。
解説動画はこちら




なぜ開票率1%で当確が出るのか?
今回は選挙のお話です。

各局がどのような仕組みで
当確を出しているかは不明ですが

少なくとも投票所の出口調査や
事前アンケートなどの結果などを用いて
統計的なサンプリング調査を元に
最終的な判断をしていると思います。


当確が分かる仕組み
無作為な1%分の投票結果が分かれば
票全体の動向が推計できます。

これはお味噌汁の味見に似ていますね。

ちゃんと掻き回したものを
お玉に一掬い程度味見すれば
味噌汁全体の味はおおよその検討はつくでしょう。

ここで用いられるのが
母比率の信頼区間です。


区間推定「母比率」の信頼区間の求め方

母比率の信頼区間を求める式
スクリーンショット 2021-11-06 16.55.09

なんだかややこしいと思いますが
R:標本比率(得票率)
z:標準化変数(Z-score)
n:標本数(サンプル)
となっています。

また信頼係数というモノがあります。

これは母集団から標本を取って
その平均からXX%信頼区間を
求めるという作業を100回やったとき
XX回はその区間の中に母平均が含まれる
というものです。

通常は95%を用いることが多いですが

信頼係数におけるzの値は
90%で1.64
95%で1.96
99%で2.58
という値になります。


さて、ここで問題を考えてみましょう。

有効投票数10万票の選挙で開票率1%(1000票)時点の
A候補者の得票率は60%でした。

このとき信頼係数95%で
母比率の信頼区間を計算してみよう。

Pythonを使って計算してみました。
#標本比率:
R=0.6
# 標準化変数
z=1.96
# 標本数
n=1000

lower = (R - z*((R*(1-R))/n)**0.5)*100
upper = (R + z*((R*(1-R))/n)**0.5)*100
print('{0:.3f} - {1:.3f}'.format(lower,upper))
56.964 - 63.036

これによると母比率の信頼区間は
最低でも56.9%、最高で63%


他に候補者がどれだけいても
過半数以上を獲得できる見込みになります。

計算式上ではサンプリングした標本数の数で
信頼区間の幅は大きく変わります。

10万票ほどの選挙区ではおよそ1%
1000票もあれば誤差は3%程度で
最終結果を導くことができます。

標本数を増やせば、区間はグッと縮まります。
開票率が上がっていけば
どんどん精度は上がりますね。

候補者同士の結果に差のない場合は
開票率100%に近付かないと
結果が出ないこともありますが

元々大差がついている選挙区では
開票率が低くても当確が出るようですね。

さてここからは
選挙区のシミュレーションをしてみましょう。

神奈川11区でシミュレーション

元セクシー担当大臣のいる選挙区の結果を用いて
シミュレーションしてみましょう。

結果は
小泉 進次郎氏 14万7634票
林 伸明氏 3万8843票
となっていました。

データ化してみます。
# 小泉票
k = ['K']*147634
# 林票
h = ['H']*38843
# 全体の票
v = k+h

print(len(v))
print(v.count('K'))
print(v.count('H'))
186477
147634
38843

これで票のデータを用意できました。
ランダムサンプリングして結果を見てみましょう。
1%でランダムサンプリング
import random

n = len(v)//100
d = random.sample(v , n)

print(len(d))
print(d.count('K'))
print(d.count('H'))
1864
1469
395

1%時の票数は1864
小泉氏は1469票獲得
林氏は395票獲得で
小泉氏の圧勝・・・・・・

一回やっただけでは分からないですよね・・・

頑張って100回対決してみましょう。
import random
import pandas as pd

n = len(v)//100
df = pd.DataFrame(columns=['小泉票','林票'])
for i in range(100):
    d = random.sample(v , n)
    k_count = d.count('K')
    h_count = d.count('H')
    tmp = pd.DataFrame([[k_count,h_count]],columns=['小泉票','林票'])
    df = df.append(tmp)

df = df.astype('int')
df.describe()
小泉票林票
count100.000000100.000000
mean1473.930000390.070000
std18.06176618.061766
min1427.000000351.000000
25%1462.000000376.000000
50%1475.000000389.000000
75%1488.000000402.000000
max1513.000000437.000000

結果から言えば
林氏はどんなに頑張っても
437票しかとれず小泉氏が圧勝です。

箱髭図にして差し上げました。
スクリーンショット 2021-11-06 17.26.44

1%の時点でこれなんで
まあ、諦めろって事ですwwwwwww

政策や人柄、人気などで
相手を上回るしかないでしょうね
まあほぼ無理ゲーでしょうけど。


まとめ
1000票ほどを集めれば
おおよその結果が予想できてしまう

得票率1%の時点で
大きく差がついていたら諦めろ

ただしデータに偏りが無いことが大前提!

あくまでもこの推定はデータに偏りがない所で
サンプリングされたデータを用いての推定です。

恣意的に歪められた結果を用いれば
作為的に誘導することも出来てしまいます。

使う側も見る側も
注意が必要なポイントです。


今回は選挙にまつわる
統計のお話でした。

それでは。

このページのトップヘ