10/25/2006

吳子青: 民意調查真的公正嗎

前言:
最近又到了選舉期了 在電視媒體或報章雜誌常常可以看到
“ 某某參選人支持率多少”…
民意支持率各家都宣稱客觀公正,但其實是可以操作的
在這裡舉出一個以前碰過的問題讓大家思考一下 

問題:

若台北市某候選人的真實 “民意支持率”為15%,找出使調查樣本的
民意支持率超過0.18 的出現機率不大於 10% 的最小樣本數 N。

----------------------------------------------------------------------
答案:

題旨與分析
這問題的思考流程是這樣的
將全部台北市民當成一個族群,而調查的對象代表抽樣的樣本
“某候選人的真實民意支持率為15%” 這句話的意思就是代表族群的支持率
而調查樣本的民意支持率就是樣本的支持 率

將這問題視為一個二項式分佈的問題,也就是支持和不支持兩種情況
支持的機率 P=0.15 不支持的機率 Q=0.85
舉例說明
如果某一次的抽樣從台北市民隨機抽10個人 (Sample Size m=10)
10個人中支持候選的人有2個人,不支持的有8個人
這個事件出現的機率為

http://photos1.blogger.com/blogger2/2907/859880749988154/1600/formula1.jpg

所以如果問題是 ”找出使調查樣本的民意支持率超過0.18”
如果抽樣人數維持10人,支持人數大於1.8的都符合條件
也就是支持人數 2 到10人分別算出的機率加總。

題目所求是 “出現機率不大於 10% 的最小樣本數 N。”所以從n=1
開始算到符合出現機率不大於10%為止。

程式流程
Step 1 : 宣告function p1(m,n) 為抽樣m個人,有n個人支持的機率

Step 2 : 計算A為抽樣m個人,支持率超過0.18的機率總和

Step 3 : 從m=1 開始增加用For 跑迴圈,決定停止條件為A < >程式內容


/ p1.m / (* 這行代表m-files p1.n 開始 *)

function output=p1(m,n)

if n>0.5*m
a=m-n;
output=prod((m-a+1):m)/prod(1:a)*(0.15)^n*(0.85)^(m-n);

else
output=prod((m-n+1):m)/prod(1:n)*(0.15)^n*(0.85)^(m-n);
end


/ pp1.m / (* 這行代表m-files pp1.n 開始 *)
clear;
max=400;
ppp1=zeros(max,2);

for m=1:max
k=ceil(m*0.18);
A=0;


if A<=0.1 fprintf('最小樣本數%d\t出現機率%d',m,A);

break
end
fprintf('最小樣本數%d\t出現機率%d\n',m,A);
clc;
end
plot (ppp1(1:max,2), 'DisplayName', 'ppp1(1:max,2)', 'YDataSource', 'ppp1(1:max,2)');
figure(gcf)
xlabel('樣本數目');
ylabel('出現機率');
/ Command windows / (* 這行代表command windows輸入 *)
pp1


執行結果
最小樣本數217 出現機率9.559103e-002
這是最後跑出來的結果
N=217為民意支持率超過0.18 的出現機率不大於 10% 的最小樣本數 N

這是程式結果




http://photos1.blogger.com/blogger2/2907/859880749988154/1600/hy2.jpg

這是圖

http://photos1.blogger.com/blogger2/2907/859880749988154/1600/hydro.jpg

討論
(1)因為老師上週的上課內容剛交到For 和If的用法,所以在這裡練習一下

(2) 程式中碰到最大的問題在於 prod () 連乘函數括號內的矩陣不能太大
從1*2*3……..*171 =prod(1:171) 這樣結果會爆掉 ,可是在算二項式分佈
的機率時就一定會用到。

所以在這裡用了一個小技巧,在p1裡當 n > 0.5 m 時 令n=m-n
因為在排列組合裡 C10取2=C10取8,10!/8!2! =10!/2!8!
在這裡可以避免連乘太多項,可以有效 避免算到M=171時,
結果一定會出現NaN。但是當m 算到300多時
仍然會出現同樣的問題。或許會有更有效率的寫法。