JSLには、組み込みの反復用プログラミング関数の他に、データテーブルの行、グループ、または行の条件付き選択を使って反復するための関数もあります。
通常、式はデータテーブルの現在の行に対してだけ実行されます。例外は、計算式列内の式、Summarize関数と統計量を事前計算する関数および分析プラットフォームがデータテーブルの列を使用する場合です。
メモ: スクリプトの現在行は、データテーブルで選択(強調表示)されている行や、データテーブルウィンドウでの現在のカーソル位置とは関係ありません。スクリプト操作の対象となる行の番号です。デフォルトではゼロ(行なし)になっています。
スクリプトのために現在の行を設定するには、For Each RowまたはRow() = Xを使用します。
Row() = 3; ...
For Each Row( ... );
For Each Rowは、現在のデータテーブルの各行に対し、スクリプトを1回実行します。Row()=1はスクリプトが実行されている間だけ有効で、実行が終了すると、Row()はデフォルトの値であるゼロに戻ります。そのため、一度にスクリプトすべてを実行したときと、一度に数行ずつスクリプトを実行したときとでは、異なる結果になる場合があることに注意してください。
この章では、現在の行を明示的に指定していない例の場合、現在の行を決定するコンテキストの中だけで実行されるものとします。現在の行とはを参照してください。
デフォルトでは、現在の行の番号は0です。テーブル内の先頭の行が行1なので、行0は原則として行がないことを表します。つまり、デフォルトでは、操作はどの行にも実行されません。現在の行を設定するか、または行のセットを指定しない限り、データがないために欠測値となります。たとえば、列名は、現在の行の該当する列の値を戻します。あいまいさを避けるために(強制的に名前を列名として解釈させるために)、接頭演算子「:」を使います。
:性別; // ""を戻す
:年齢; // .を戻す
接頭演算子を使うことで、実際には1行だけに基づいているのに、データテーブル全体に当てはまるように見える結果を取得しないようにするためです。また、大部分の環境で、値をあいまいな名前に割り当てた場合に、不用意にデータ値が上書きされないようにします(このような事態を完全に防ぐには、接頭または間に入れる演算子「:」を使ってデータ列を明確に参照し、接頭演算子「::」を使ってグローバルスクリプト変数を明確に参照します。高度な適用範囲指定と名前空間を参照してください。
Row()関数を使って、現在の行の番号を取得または設定できます。Row()は、JSLのL-value式の一例です。この関数は、代入演算子(=、+=など)の前に置いて値を設定しない限り、デフォルトの値を戻します。
Row(); // 現在の行の番号を戻す(デフォルトでは0)
x = Row(); // 現在の行の番号をxに格納する
Row() = 7; // 7番目の行を現在の行にする
Row() = 7; :年齢; // 7番目の行を現在の行にし、12を戻す
現在の行の設定は、ユーザが選択して実行するスクリプト部分が終わるまで有効です。スクリプトの実行が終わると、現在の行の設定はデフォルト(行0または行なし)にリセットされます。そのため、同じスクリプトでも、一度にすべて実行した場合と数行ずつ実行した場合では、異なる結果が出ることがあります。
N Rows()関数とN Cols()関数は、データテーブル内の行と列の数をそれぞれカウントします。
N Rows( dt ); // 行数
N Cols( dt ); // 列数
N RowsとN Colsは、行列内の行の数もカウントします。NRowとNColは同義語です。詳細については、問い合わせ関数を参照してください。
現在のデータテーブルの各行にスクリプトを繰り返すには、スクリプトにFor Each Rowを入れます。
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
For Each Row( If( :年齢 > 15, Show( :年齢 ) ) );
開いているデータテーブルを指定するには、第1引数としてデータテーブル参照を含めます。
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt2 = Open( "$SAMPLE_DATA/San Francisco Crime.jmp" );
For Each Row( dt1, If( :年齢 > 15, Show( :年齢 ) ) );
For Each Rowは、データテーブルに新しい計算式列を作成するのではなく、行の属性を設定するために使います。次の2つのスクリプトは似ていますが、最初のスクリプトでは行の属性列を作成し、For Each Rowのスクリプトでは列を作成せずに行の属性を設定します。
New Column( "行の属性", Row State, Formula( Color State( :年齢 - 9 ) ) );
For Each Row( Color of( Row State() ) = :年齢 - 9 );
指定した条件に一致する各行にスクリプトを繰り返すには、For Each RowとIfを組み合わせます。
For Each Row( Marker of( Row State() ) = If( :性別 == "F", 2, 6 ) );
For Each Rowループの実行を制御するには、BreakとContinueを使用します。BreakおよびContinueを参照してください。
Dif()とLag()は、統計量の計算、特に時系列データや累積データを処理するときに有効です。
• Lag()は、現在の行からn行前の列の値を戻します。
• Dif()は、現在の行の列の値とn行前の列の値との差を戻します。
以下の式は同じ結果になります。
dt << New Column( "身長の差" );
For Each Row( :身長の差 = :"身長(インチ)"n - Lag( :"身長(インチ)"n, 1 ) );
For Each Row( :身長の差 = Dif( :"身長(インチ)"n, 1 ) );
Sequence()は、計算式エディタのSequence関数に相当し、テータテーブル列のセルを埋めるのに使用します。4つの引数のうち、後の2つはオプションです。
Sequence( from, to, stepsize, repeat );
必須である開始値(from)と終了値(to)は、セルに挿入する値の範囲を指定します。from=4、to=8とした場合、セルは4、5、6、7、8、4、...という値で埋められます。
ステップサイズ(stepsize)はオプションです。指定しない場合のデフォルト値は1です。ステップサイズは範囲内の値の増分です。上記のfromとtoの値を使い、stepsize = 2とした場合、セルは4、6、8、4、6、...という値で埋められます。
繰り返し(repeat)はオプションです。指定しない場合のデフォルト値は1です。繰り返しは、次の値にインクリメントするまでに同じ値を繰り返す回数を指定します。上記のfrom、toおよびstepsizeの値を使い、repeat=3とした場合、セルは4、4、4、6、6、6、8、8、8、4、...という値で埋められます。繰り返し値(repeat)を指定した場合は、ステップサイズ(stepsize)も指定しなければなりません。
列のすべての行が埋まるまで数列(シーケンス)が繰り返されます。
dt = New Table( "Sequence Example" ); // 新しいデータテーブルを作成する
dt << New Column( "5まで数える" ); // 2列を追加する
dt << New Column( "4間隔で17まで数える" );
dt << Add Rows( 50 ); // 50行を追加する
/* 最初の列を1、2、3、4、5、...の数列で埋める
2列目を1、1、5、5、9、9、13、13、17, 17、...の数列で埋める*/
For Each Row (
Column( 1 )[ ] = Sequence( 1, 5 );
Column( 2 )[ ] = Sequence( 1, 17, 4, 2 );
);
Sequence()は計算式関数なので、列の計算式にSequence()を設定して列を埋めることもできます。次の例では「Sequence 関数の計算式」という新しい列を作成し、それに計算式を追加しています。この計算式によって作成される数列は、25から29までの値をそれぞれ回繰り返しながら、1ずつ増加します(25、25、26、26、27、27、28、28、29、29、25、...)。
dt = New Table( "Sequence関数の計算式の例" );
dt << Add Rows( 20 );
dt << New Column( "Sequence関数の計算式", Formula( Sequence( 25, 29, 1, 2 ) ) );
Sequence()の結果例をさらにいくつか紹介しましょう。
• Sequence(1,5)の場合、1,2,3,4,5,1,2,3,4,5,1,...となります。
• Sequence(1,5,1,2)の場合、1,1,2,2,3,3,4,4,5,5,1,1,...となります。
• Sequence(10,50,10)の場合、 10,20,30,40,50,10,...となります。
• 10*Sequence(1,5,1)の場合、10,20,30,40,50,10,...となります。
• Sequence(1,6,2)の場合、1,3,5,1,3,5, ...となります。リミットはありません。
メモ: 通し番号の値で行列を作成したい場合は、Sequence関数ではなく、Index関数を使用します。