リスト処理とデータの集計
Cindyscriptのリスト処理関数を用いて,データの集計などを行います。
例として,高校生男子の新体力テストのデータ40人分のデータを用います。(もっと多くても原理は同じです)
サンプルデータは,このページの下部からダウンロードできます。
記録データを取り出す
読み込んだデータには,インデックスとして,種目名,生徒番号があるので,記録の数値だけを取り出したリストを作ると処理がしやすいでしょう。
dlist=Readcsv("sports.csv");
rown=length(dlist);
coln=length(transpose(dlist));
data=apply(dlist_(2..rown),#_(2..coln));
で記録の数値だけを取り出すことができます。rownは行数,colnは列数を表しますが,dlist は40人分のデータとインデックスで,rown=41行分のリストからできています。1行分のリストには coln=9 の要素があります。
2..rown で,リスト [2,3,4,・・・・41] ができます。2..coln でリスト[2,3,・・・,9] ができます。したがって,dlist から2行目以降を取出したリスト dlist_(2..rown) に対し,#_(2..coln) でそれぞれの行の第2要素からあとを取り出すことができます。apply() により,そうしてできたリストを作っています。
データの集計
記録の縦横の最大・最小・平均などを求めますが,この例では個人ごとの集計は無意味なので,種目ごとの集計をします。試験の成績であれば,縦横とも行うところです。
まず,最大,最小です。リストの要素の最大値,最小値は,max(list),min(list) で求められます。
50m走は,リスト data の第1列ですので,第n列目を抽出するCindyScriptの関数 column(list,n)を使います。
list=column(data,1);
println(max(list));
println(min(list));
を実行してみると,8 と 6.3 が コンソールに表示されます。
次に平均値ですが,average() 関数はないので,合計sum(list) をデータ数 length(list) で割って求めます。
println(sum(list)/length(list));
もし40人の中で50m走を計測していない(データがない)人がいる場合は,データがあるものだけを対象にする必要があります。データがない場合は,要素が空 ("" ) になっているものとします。
条件を指定して要素を抽出するには select(list,条件) を使います。
list=select(column(data,1),#!="");
ここで,# はリストの要素を表す変数だと思ってください。試しに,何人かデータを消してみましょう。
forall(4..9,data_#_1="");
println(length(list));
で,4番から9番までを消去し,データが減ったことを確かめられます。
データのあるなしがわからない場合や,データ量が多くてチェックが面倒な場合は,このように抽出してから処理するのがよいでしょう。
以上の処理を8種目について行い,結果をリストに格納します。繰り返しの repeat() を使うのが平易です。
table=[];
repeat(8,s,
list=select(column(data,s),#!="");
num=length(list);
mx=max(list);
mn=min(list);
av=sum(list)/num;
table=append(table,[num,mx,mn,av]);
);
Dispmat(table);
ここで, table=append(table,[num,max,min,average]); の append はリストの後方に要素を追加する関数です。repeat の前に,中身のない table を用意しておき,table の後方に[num,max,min,average]を追加したものをあらためて table としています。これを8回繰り返すと,次々に計算結果が追加されていきます。
Dispmat(table); で,できた表をコンソールに表形式で表示します。
コンソールには
40 8 6.3 7.04
40 282 173 244.12
40 40 20 30.78
40 74 45 61.95
40 55 30 37.65
40 74 42 60.85
40 55 25 39.52
40 7.36 4.38 5.7
が出力されます。
では,KeTCindyの作表関数を使って,これを一覧表にしましょう。
Yoko=[20]++apply(1..(coln-1),30);
Tate=apply(1..5,10);
Tabledatalight("",Yoko,Tate,[],[0,"Rng=n"]);
Putrow(1,"c",[""]++dlist_1_(2..9));
PutcoL(1,"c",["","人数","最大","最小","平均"]);
repeat(8,s,
repeat(4,t,Putcell(s+1,t+1,"r",table_s_t));
);
データの検索と抽出:度数カウント
前項で,select(list,条件) で条件に合う要素を抽出できることがわかりました。これを用いて,度数分布を求めることができます。
50m走の記録は6.3秒から8秒まであることがわかりました。
そこで,6.0から0.5秒刻みでデータの個数をカウントしましょう。
6.0<x≦6.5 と,右側に等号をいれると,最大値の8.0がちょうど入ります。
50m=select(column(data,1),#!="");
freq=[0,0,0,0];
repeat(4,s,
d1=6.0+(s-1)*0.5;
d2=6.0+s*0.5;
freq_s=length(select(50m,d1<# & #<=d2));
);
println("freq="+freq);
ここで,結果を格納するリスト freq は,最初 [0,0,0,0] にしています。
データ数(段階)が4であることがわかっていて,なければ0であることもわかっているからです。
すると,繰り返しのときには,s番目のデータを書き換えればよいので freq_s=length(select(50m,d1<# & #<=d2)); としています。
前項のように,append() を使っても構いません。
コンソールには [6,17,12,5] と表示されます。
なお,ヒストグラムを描くのであれば,KeTCindyの関数 Histplot() を使うことができます。
並べ替え
データを並べ替えて,ベスト5を抽出します。
並べ替えは sort(list) を使います。昇順に並べ替えられます。戻り値は並べ替えたリストです。
ベスト5には該当者の番号も必要ですから,元データから種目名だけを取り除いたリストをdata とします。
sort() では,第2引数に条件を指定することができます。sort(data,#_2) とすると,第2要素で並べ替えられます。
また,種目によって,昇順に並べるものと,降順に並べるものがあります。8種目について,昇順/降順の別を調べると次のようになります。
50m走 昇順
立ち幅跳び 降順
ハンドボール 降順
反復横跳び 降順
上体起こし 降順
長座体前屈 降順
握力 降順
持久走 昇順
この昇順/降順の別を,リスト [0,1,1,1,1,1,1,0] とし,0なら昇順,1なら降順として並べ替えることにします。
ベスト5は5人とは限らないことに注意しましょう。5人目の記録をとり,それ以下(以上)の者を選び出す必要があります。種目によってこの人数も変わるので,表を作成するために最大人数 maxnin を調べておきます。
dlist=Readcsv("sports.csv");
rown=length(dlist);
coln=length(transpose(dlist));
data=dlist_(2..rown);
best5=[];
direc=[0,1,1,1,1,1,1,0];
repeat(8,s,
dt=select(data,#_(s+1)!="");
sortdata=sort(dt,#_(s+1));
if(direc_s==1,
sortdata=reverse(sortdata);
border=sortdata_5_(s+1);
member=select(sortdata,#_(s+1)>=border);
,
border=sortdata_5_(s+1);
member=select(sortdata,#_(s+1)<=border);
);
best5=append(best5,member);
);
maxnin=max(apply(1..8,length(best5_#)));
これで,リスト best5 ができるので,表にして表示します。番号(氏名があれば氏名にする)に,記録を括弧づけでつけます。
Yoko=[20]++apply(1..(coln-1),30);
Tate=apply(1..(maxnin+1),10);
Tabledatalight("",Yoko,Tate,[],[0,"Rng=n"]);
Putrow(1,"c",[""]++dlist_1_(2..9));
PutcoL(1,"c",[""]++(1..maxnin));
repeat(8,s,
repeat(length(best5_s),t,
Putcell(s+1,t+1,"r",best5_s_t_1+" ("+best5_s_t_(s+1)+")");
);
);
< 「KeTCindyCalc」に戻る >