04 5数要約と箱ひげ図
データの最大値,最小値,第1四分位数,中央値,第3四分位数で分布の特徴を表すことを5数要約といいます。これを図にしたのが箱ひげ図です。
四分位数の求めかた
データを昇順に並べたとき
下から4分の1の位置にあるデータを第1四分位数
下から4分の2の位置にあるデータを第2四分位数
下から4分の3の位置にあるデータを第3四分位数
といいます。第2四分位数は中央値(メジアン)と同じです。
まず,中央値の求め方を考えましょう。
データの個数が偶数ならちょうど半分に分けられますので,区切りのところを2つの値の平均を取ります。
データの個数が奇数なら中央の位置のデータが中央値です。
次に,第1四分位数と第3四分位数です。
データの個数が偶数ならちょうど半分に分けられますので,下半分の中央値を第1四分位数,上半分の中央値を第3四分位数とします。
データの個数が奇数なら中央のデータを除いて,残りを2つに分け,それぞれの中央値で第1,第3四分位数が決められます。
以上は,高校の教科書にある四分位数の説明です。
実は,四分位数の求め方は他にもあります。
データの個数をn,第1四分位数はq=1/4,第3四分位数はq=3/4 として t=1-q+q*n とし,
tが整数ならt番目の値,そうでなければ,rをtの直前の整数,sをrの直後の整数として
(s-t)×(r番目の値)+(t-r)×(s番目の値)
とします。
統計ソフトのRは,この方法で四分位数を求めています。GeoGebraは前者の方法です。
ここでは,2通りの方法をやってみましょう。
中央値を求める
原理は簡単なので,すぐコーディングできるでしょう。データを引数として中央値を返す関数を作りましょう。並べ替えは組み込み関数 sort() を使います。偶数かどうかの判定は iseven() を使います。
median(data):=(
regional(ret,sortdata,n);
sortdata=sort(data);
n=length(sortdata);
if(iseven(n),
ret=(sortdata_(n/2)+sortdata_(n/2+1))/2;
,
ret=sortdata_((n+1)/2);
);
);
四分位数を求める:その1
中央値を利用すれば簡単に求められますね。引数をデータと分位数として,分位数が2でもよい(中央値が戻る)ことにしましょう。
quantile(data,q):=(
regional(len,ret,sortdata,data1,data3);
len=length(data);
sortdata=sort(data);
if(q==2,ret=median(data));
if(q==1 % q==3,
if(iseven(len),
data1=sortdata_(1..len/2);
data3=sortdata_(len/2+1..len);
,
data1=sortdata_(1..((len-1)/2));
data3=sortdata_(((len+1)/2+1)..len);
);
if(q==1,ret=median(data1),ret=median(data3));
);
ret;
);
四分位数を求める:その2
Rで使っている方法です。引数は quantile()と同じです。
quantileR(data,q):=(
regional(ret,sortdata,n);
sortdata=sort(data);
n=length(data);
t=1-q/4+q/4*n;
if(isinteger(t),
ret=sortdata_t,
ret=(ceil(t)-t)*sortdata_(floor(t))+(t-floor(t))*sortdata_(ceil(t));
);
ret;
);
箱ひげ図を描く
データの最大値は max(data),最小値は min(data) で求められるので,これで5数要約が揃います。
あとは適当に表示位置などをデザインして箱ひげ図を描けばよいでしょう。
次はその一例です。引数は,データと範囲 range(範囲は最小値,最大値を求めて適当に決めます),表示位置 ps です。表示範囲を20としています。箱と5数要約を書くためにすこしコードが長くなりますが,やっていることはたいしたことはありません。第1象限に drawtable([0,0],datalist)で描いた表があるので,第4象限に描くようにしていますが,これも適宜変更可能ですね。
boxplot(data,range,ps):=(
regional(len,qrange,q1,q2,q3,qscale,qx0,qx1,qx2,qx3,qx4,qy);
len=length(data);
qrange=range_2-range_1;
q1=quantile(data,1); // 第1四分位数
q2=quantile(data,2); // 中央値
q3=quantile(data,3); // 第3四分位数
qscale=20/qrange;
apply(0..10,drawtext([ps_1+#*2-0.4,ps_2-0.8],range_1+#*qrange/10));
qx0=ps_1+(min(data)-range_1)*qscale;
qx1=ps_1+(q1-range_1)*qscale;
qx2=ps_1+(q2-range_1)*qscale;
qx3=ps_1+(q3-range_1)*qscale;
qx4=ps_1+(max(data)-range_1)*qscale;
qy=ps_2;
drawtext([-6,qy+3]," 最大値 :"+max(data));
drawtext([-6,qy+2],"第3四分位数:"+q3);
drawtext([-6,qy+1]," 中央値 :"+q2);
drawtext([-6,qy+0],"第1四分位数:"+q1);
drawtext([-6,qy-1]," 最小値 :"+min(data));
fillpoly([[qx1,qy],[qx3,qy],[qx3,qy+2],[qx1,qy+2]],color->[1,1,0.5]);
drawpoly([[qx1,qy],[qx3,qy],[qx3,qy+2],[qx1,qy+2]]);
draw([qx2,qy],[qx2,qy+2]);
draw([qx0,qy+1],[qx1,qy+1]);
draw([qx0,qy+0.8],[qx0,qy+1.2]);
draw([qx3,qy+1],[qx4,qy+1]);
draw([qx4,qy+0.8],[qx4,qy+1.2]);
);
以上はユーザー定義関数なので Initialization スロットに書き,Drawスロットには次の2行を書きます。
(data を決めたあとです)
drawtext([-7,-1],"立ち幅跳び");
boxplot(data,[170,290],[0,-5]);