目次
前
次
成績集計(AWK)
教育機関で講義、実習を担当していると
試験をしてから点数を集計し、統計処理
が必要になります。
統計として、次の項目が要求されたりします。
これらの内容は、パーソナルコンピュータが
普及した現在では、表計算ソフトを利用する
のが定番なのでしょう。
表計算ソフトをインストールするのが面倒で
専らスクリプトを書いて対応しています。
次のようなフォーマットで、テキストファイルに
学生番号と各問の点数が入った状態で集計と統計
を出してみます。
201301 6 9 8 3 6 6 6 6
201302 1 2 2 1 1 3 7 5
201303 7 3 4 2 9 3 3 6
201304 1 1 9 3 2 4 2 1
201305 9 4 1 10 3 4 2 1
201306 1 9 3 10 3 7 3 10
201307 7 2 1 4 9 4 5 2
201308 4 4 4 8 9 9 3 5
201309 8 4 4 10 9 3 8 5
201310 1 6 8 10 3 4 10 9
201311 8 1 7 9 3 3 9 7
201312 6 9 10 8 1 2 5 4
201313 8 2 8 4 8 1 1 3
201314 4 10 5 2 8 7 1 3
201315 3 1 6 9 2 5 8 8
201316 6 3 2 1 10 7 3 5
201317 1 9 2 2 1 8 9 3
201318 9 2 3 8 9 9 9 5
201319 4 10 7 2 1 1 5 9
201320 9 1 3 8 1 9 5 10
フィールドでみると2から9に8問に
点数が入っているので、まず合計を
求めます。
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%s total(%3d)\n",$0,result)
# print $0 " total(" result ")"
}
フィールド数は、組込み変数NFに入っている
ことから、第2から最終フィールドまで加算
してしまえば、合計になります。
フィールド数を使えば、問の数は任意で処理
できるので、合計を求める処理は、問の数が
変わっても使いまわせます。
実際に処理すると、次のようになります。
最高点、最低点、平均を求めるには
合計を求めた後で処理します。
ENDクローズで計算すればよいでしょう。
初期化はBEGINクローズで指定します。
BEGINクローズは、最高点、最低点、平均の
値を初期すればよいので、次のようにします。
BEGIN {
xmax = 0
xmin = 10000
xavr = 0
}
ENDクローズでは、平均を求めて最高点、最低点
平均を表示します。レコード数が組込み変数に
入っているので、これで計算します。
END {
xavr /= NR
printf("max(%d) min(%d) avr(%d)\n",xmax,xmin,xavr)
# print "max(" xmax ") min(" xmin ") avr(" xavr ")"
}
最高点、最低点は、1ライン毎に合計が
求められているので、その合計と仮設定
の最高点、最低点を比較して求めます。
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%s total(%3d)\n",$0,result)
# print $0 " total(" result ")"
# calculate xmax
if ( xmax < result ) {
xmax = result
}
# calculate xmin
if ( xmin > result ) {
xmin = result
}
# calculate total
xavr = xavr + result
}
ひとつのスクリプトにまとめると以下。
BEGIN {
xmax = 0
xmin = 10000
xavr = 0
}
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%s total(%3d)\n",$0,result)
# print $0 " total(" result ")"
# calculate xmax
if ( xmax < result ) {
xmax = result
}
# calculate xmin
if ( xmin > result ) {
xmin = result
}
# calculate total
xavr = xavr + result
}
END {
xavr /= NR
printf("max(%d) min(%d) avr(%d)\n",xmax,xmin,xavr)
# print "max(" xmax ") min(" xmin ") avr(" xavr ")"
}
スクリプトを実行すると、次のようになります。
得点の状況を見たいときには、合計を'*'の個数で
表示すればよいでしょう。
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%d :",$1);
for ( i = 0 ; i < result ; i++ ) {
printf("*")
}
printf("\n")
# print ""
}
得点状況は、次のようになります。
CUIでは、1行が80桁程度なので、100点満点
のような試験で得点は、2で割る等で80桁の
中に入るようにすればよいでしょう。
ヒストグラムは、点数の範囲を区切って処理
すればよいので、カテゴリーをBEGINクローズ
の中に入れて対応します。ENDクロースには
ヒストグラム表示を担当させます。
BEGIN {
h0 = 0
h1 = 0
h2 = 0
h3 = 0
h4 = 0
h5 = 0
h6 = 0
h7 = 0
h8 = 0
}
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%s total(%3d)\n",$0,result)
# class
if ( result < 10 ) { h0 = h0 + 1 }
if ( result < 20 && result > 9 ) { h1 = h1 + 1 }
if ( result < 30 && result > 19 ) { h2 = h2 + 1 }
if ( result < 40 && result > 29 ) { h3 = h3 + 1 }
if ( result < 50 && result > 39 ) { h4 = h4 + 1 }
if ( result < 60 && result > 49 ) { h5 = h5 + 1 }
if ( result < 70 && result > 59 ) { h6 = h6 + 1 }
if ( result < 80 && result > 69 ) { h7 = h7 + 1 }
if ( result > 89 ) { h8 = h8 + 1 }
}
END {
printf("\histgram \n");
printf("0: "); for ( i = 0 ; i < h0 ; i++ ) { printf("*") ; } print "";
printf("1: "); for ( i = 0 ; i < h1 ; i++ ) { printf("*") ; } print "";
printf("2: "); for ( i = 0 ; i < h2 ; i++ ) { printf("*") ; } print "";
printf("3: "); for ( i = 0 ; i < h3 ; i++ ) { printf("*") ; } print "";
printf("4: "); for ( i = 0 ; i < h4 ; i++ ) { printf("*") ; } print "";
printf("5: "); for ( i = 0 ; i < h5 ; i++ ) { printf("*") ; } print "";
printf("6: "); for ( i = 0 ; i < h6 ; i++ ) { printf("*") ; } print "";
printf("7: "); for ( i = 0 ; i < h7 ; i++ ) { printf("*") ; } print "";
printf("8: "); for ( i = 0 ; i < h8 ; i++ ) { printf("*") ; } print "";
}
このスクリプトで、ヒストグラムを表示させると
次のようになります。
ヒストグラム表示で、ある程度の得点の分布が
わかりますが、最後に標準偏差を求めてみます。
標準偏差は、分散の平方根なので、分散を
求めてから、SQRTで平方根を計算します。
分散は、得点と平均の差の2乗の合計をサンプル数
で割った商という公式で求めます。
文章で書くと面倒ですが、スクリプトにすると
簡単です。
BEGIN {
xsqr = 0
xavr = 0
x[0] = 0
}
{
result = 0
for ( i = 2 ; i < NF+1 ; i++ ) {
result += $i
}
printf("%s total(%3d)\n",$0,result)
# print $0 " total(" result ")"
# store
x[NR] = result
}
END {
# average
for (e in x) {
xavr += x[e]
}
xavr /= NR
# variable
for(e in x){
xsqr += (x[e] - xavr) ^ 2
}
ss = sqrt(xsqr/NR)
printf("average(%d) ss(%d)\n",xavr,ss)
# print "average(" xavr ") ss(" ss ")"
}
平均、標準偏差を求めると、次のようになります。
一度スクリプトを作成すると、使い回しが
できるので、表計算ソフトと違い、採点と
テキストファイルへの入力に集中できます。
WindowsのDOS窓、Unixの端末、Macの端末、MS-DOS等で
AWKが動作すれば、どんな環境でも利用できます。
MS-DOSのようにネットワークに接続できないコンピュータ
環境を使うと、セキュリティ上の問題を回避できます。
SpreadSheet(表計算ソフト)を動かせない、非力な
コンピュータであっても、成績集計ができます。
目次
前
次