データ操作

ワークシート

ワークシートセルの選択と色付け

Originには、条件付き選択のために2つのXファンクションwcellselwxtがあります。wcellselはワークシート内の任意のセル範囲をベースにしています。wxtは列レベルで動作するワークシートの抽出ダイアログに相当します。

次のコードは、Xファンクションwcellselを使って、条件に合うセルを選択し、wcellcolorを使って色付けします。

// いくつかの列にランダムデータを持つ新しいブックを作成
newbook;
newsheet cols:=6 xy:="Y";
loop(i,1,6){wcol(i)=normal(100)};
// 0.5以上の値を持つ全てのセルを選択し、色付け
wcellsel 1:end c:=ge v:=0.5;
wcellcolor c:=color(green);
wcellcolor c:=color(red) type:=1;
wcellsel; // セルの選択を解除して色を表示

wxtでワークシート行の色付け

wcellselはワークシートセルを選択できますが、セル入力範囲で条件に合ったものを選択することしかできません。行を選択し、詳細な条件が必要な場合、Xファンクションwxtを使います。これはワークシートクエリダイアログのLabTalk版ともいえます。次のサンプルを実行する前に、ランダムデータを持つ2列を用意してください。

//アクティブワークシートで、col(2)>0.3という
//条件に合う行を選択(sel:=1)
wxt "col(2)>0.3" sel:=1;

//選択されたセルの色を変更する 
wcellcolor c:=color(green);

//ワークシートの選択を解除して色を確認
wcellsel;

テキスト列にwxtを使用

条件にテキストが含まれる時には、注意が必要です。次のサンプルでは、テキスト列と数値列の両方を選択するための複雑な条件を使用します。

//自動車のメーカー、車種ごとの特性が入力されたデータをインポート
fname$=system.path.program$ + "Samples\Statistics\automobile.dat";
newbook;
impasc options.sparklines:=0;
// ワークシート内で make=Acura かつ Gas Mileage > 11 の行をすべて選択
// range変数を使用して、クエリを"col(Make)[i]$"より読みやすく記述
range car=col(Make);
// 文字列変数を使用して" "の中に文字列を記述しなくていいようにする
string str="Acura";
//wxt は "=" を "=="、"and" を "&&" として扱う
wxt "car=str$ and col(Gas Mileage)>11" sel:=1; // 行を選択
wcellcolor c:=color(green); // 選択された行を色付け
wcellsel; // 選択をクリア

新しいシートのデータをコピー/貼り付けして転置

このコードは、Xファンクションcopydataを使用して数値データのブロックを新しいワークシートにコピーし、その後Xファンクションwtranspose でデータを転置します。

//乱数が入力された6列を持つ新規ワークブックを作成
newbook;
newsheet cols:=6 xy:="Y";
loop(i,1,6){wcol(i)=normal(100)};
//ワークシート内のブロックを選択
worksheet -s 3 3 4 6;  
//選択されたブロックを新しいワークシートにコピー
copydata  orng:=<new>!<new> clear:=1;
//結果ワークシートを転置
wtranspose;

Xファンクションcopydataはテキストデータでは動作しません。数値と文字列両方を含むデータブロックの場合は、range -v表記を使用してブロックを範囲変数として定義し、元のブロックを新しいブロックに割り当てて値を貼り付けてください。その後、wtranspose を使用してデータを転置します。

/新しいブックにサンプルデータをインポート
fname$=system.path.program$ + "\Samples\Statistics\Protein Consumption in Europe.dat";
newbook;
impasc;
//文字列データのブロックを定義
int nc = 4; // ブロック内の列数
int nr = 10; // ブロック内の行数
int fi = 4 + nr; // ブロックの最後の行番号
range -v r1 = 1[4]:$(nc)[$(fi)]; // Set input range
//新しいワークシートを作成 ;
newsheet;
wks.ncols = nc; 
int fo = 1 + nr; // 結果範囲の最終行番号
range -v r2=1[1]:$(nc)[$(fo)];  // 結果範囲をセット
// r1の値をr2に割り当て
r2=r1; 
//ブロックを転置
wtranspose;
// 最初の行をロングネームとして設定
wrow2label longname:=1

データを新しいシートに分割、抽出

ここでは、Xファンクションdiscfreqs および wxtを使用して、データの抽出を行い、離散度数を個別のシートに置きます。Xファンクションdiscfreqsは、OriginProでのみ使用できます。

 
//新しいブックを作成し、データファイルをインポート
newbook sheet:=1; 
string fname$ = system.path.program$ + "Samples\Data Manipulation\US Metropolitan Area Population.dat";
impASC;
 
//処理する列をRange変数に格納する
range cc = [%(page.name$)]%(wks.name$)!col(4); 
string originalsheet=%(wks.name$);
 

// 分割した変数のために新しく2列を作成
wks.nCols = wks.nCols + 2;
wks.col5.lname$=City ;
wks.col6.lname$=State;

 
// 範囲内の各エントリで繰り返す..
 
for (ii=1; ii<=cc.getsize(); ii++)
{
        initialItem$=cc[ii]$; //セルの文字列を作成..
        // 新しい2列のii番目のセルに変数を書き込む...
        Col(City)[ii]$=initialitem.gettoken(1,',')$; 
        Col(State)[ii]$=initialitem.gettoken(2,',')$;
}
 
// 新しい"State"行を分析して、度数を調べる
discfreqs irng:=col(State) rd:=[<input>]Frequency!;
 
// Range変数を定義する
range ff = [%(page.name$)]Frequency!col(1);
 
// 度数出力から各Stateの値でループ
for (jj=1; jj<=ff.getsize(); jj++) 
{
        // この文字列が各反復の度数表の
        //  異なる行を指す条件にする
        string state$ = [%(page.name$)]2!col(1)[jj]$; 
        // 文字列を条件の一つとするとき
        //  Xファンクション wxt は"[i]"を含める必要がある
        string statequote$ = ""%(state$)""; 
        string cond$ = "col(6)[i]$==" + statequote$; 
        // Wxtは元のシートに対応する各行を、
        // 新しいシートに抽出
        wxt test:=cond$ iw:=1 ow:="%(state$)"; 
}

ワークシートをサブグループ化して新しいワークシートに出力

ここでは、Xファンクションdiscfreqs および wxtを使用して、データの抽出を行い、離散度数を個別のシートに置きます。Tree と StringArray変数は、度数カウントの結果を保持するのに使用します。Xファンクションdiscfreqsは、OriginProでのみ使用できます。

//新しいブックを作成しデータファイルをインポート
newbook sheet:=1;
string fname$ = system.path.program$ + "Samples\Statistics\automobile.dat";
impASC;

//Range変数に必要な列を格納
range makeCol = [%(page.name$)]%(wks.name$)!col(make);
range sourceWks = [%(page.name$)]%(wks.name$)!;

//度数カウントの結果を入力するツリーを作成し、
//"Make" 列に度数カウントを実行
//このXファンクションはOriginProでのみ有効
tree tr;
discfreqs irng:=makeCol rd:=tr;

//文字列配列を作成し、"Make"の度数を入力
StringArray sa;
sa.append(tr.FreqCount1.Data1);

//sa にデータが含まれている場合、
//"Make"で繰り返す
//そして、元のワークシートから新しいワークシートにデータを抽出する
if (sa.GetSize() != NANUM)
{
        for (ii=1; ii<=sa.GetSize(); ii++)
        {
                //この文字列は、各反復で文字列配列に
                //格納された"Make"を指す
                //条件のために使用される
                string newWk$ = sa.GetAt(ii)$;

                //wxtのテスト条件を構築
                string cond$ = "makeCol$==" + newWk$;

                //wxtはテストに従って元のシートの行を抽出し、
                //対応するMakeの値で名前付けされた 
                //ワークシートに置く
                wxt test:=cond$ iw:=sourceWks ow:=[<input>]<new %(newWk$)>;
        }
}

外れ値をマスクする

このスクリプトは、Xファンクション rowstats と wcellmaskを使用して行に記述統計を実行し、外れ値として定義された値のセルにマスクをかけます。

// 新しいブックを作成してデータファイルをインポート
newbook sheet:=1;
string fname$ = system.path.program$ + "Samples\Graphing\Contour.dat";
impASC;

// 列と行の数を取得
int nCols = wks.nCols;
int nRows = wks.nRows;

// 平均値と標準偏差のための列を追加
col(nCols+1)[L]$=Mean;
col(nCols+2)[L]$=SD;

// 行の統計を実行
rowstats -r 0 irng:=col(1)[1]:col($(nCols))[nRows] mean:=col(Mean) sd:=col(SD);

// 外れ値をマスク
for(int ii=1; ii<=nRows; ii++)
{
        double dLower = col(Mean)[ii]-col(SD)[ii];  // 平均値-標準偏差
        double dUpper = col(Mean)[ii]+col(SD)[ii];  // 平均値+標準偏差
        for(int jj=1; jj<=nCols; jj++)
        {
                double dOutlier = col($(jj))[ii];  // セル値を取得
                if(dOutlier<dLower || dOutlier>dUpper)
                {
                        wcellmask irng:=col($(jj))[ii];  // セルをマスク
                }
        }
}

行列

RGBイメージ行列

行列は、表示する行と列がいくつあるかという情報を含みますが、それは線形配列として内部的に格納されています。そのため、行列からワークシート列にデータをコピーし、以下のことが行えます。

  1. 画像ファイルをインポート
  2. 赤、緑、青(RGB)チャネルを抽出(行列から行列)
  3. チャネルデータをコピー(行列から列)
  4. RGB値の文字列表現を構築
  5. RGB値のヒストグラムを計算
// サンプル画像を指定してインポート
fname$ = SYSTEM.PATH.PROGRAM$ + "Samples\Image Processing and Analysis\Flower.jpg";
impImage;
// RGBを、赤、緑、青それぞれの行列に分割
imgRGBsplit r:=[RGBOUT]RED!1 g:=[RGBOUT]GREEN!1 b:=[RGBOUT]BLUE!1;
// 新しいワークブック作成
newbook;
wks.ncols = 6;
wks.col1.lname$ = Red;
wks.col2.lname$ = Green;
wks.col3.lname$ = Blue;
wks.col4.lname$ = RGB;
wks.col5.lname$ = Value;
wks.col6.lname$ = Count;
// ワークシート範囲
range raDR = 1, raDG = 2, raDB = 3, raDRGB = 4;
// 行列範囲
range raR = [RGBOUT]RED!1;
range raG = [RGBOUT]GREEN!1;
range raB = [RGBOUT]BLUE!1;
// 行列からワークブックにrange割り当てでデータをコピーする
raDR = raR;
raDG = raG;
raDB = raB;
// RGBを表示するための文字列を作成
col(D) = col(1)$ + " " + col(2)$ + " " + col(3)$;
// ヒストグラムを計算
discfreqs irng:=raDRGB rd:=col(Value);

複数行列をワークシートに変換

X, Y, Intensityデータがすべての高さZについて、ロングネームが"Z2um"、"Z4um"、"Z6um"…という名前の行列ブックが20個あるとします(Z方向に 20の高さでスキャン)。ここで「Z」と「um」の間の数字はZ高さを意味します。スキャンしたすべてのXYIntensity行列をXYZI構造の1つのワークシートに結合します。

これは、3D 共焦点顕微鏡画像およびタイムラプス画像での一般的なルーチンです。

doc -e M 
{
        string strMat$ = page.longname$;
        strMat$ = strMat.Between("Z","um")$; // 行列ブックのロングネームからZ値を取得
        int ZHeight = %(strMat$);
        m2w method:=xyz; // 行列を XYZに変換
        wks.addcol(); // Z列を追加
        csetvalue col:=col(4) formula:="ZHeight"; // 行列のロングネームから抽出した数値から値を設定
}

//変換ワークシートを1つに追加
string strPWKB$ = page.name$; // 現在のワークブックを親ワークブックにする
string strPWKS$ = wks.name$; // 他のシート追加のために現在のシートを記録

doc -e W
{
        string strTempWKB$ = page.name$; // 現在のワークブックのショートネーム
        if (strTempWKB$ != strPWKB$) // 親ワークブックがない場合追加開始
        {
                wAppend irng:=([%(strPWKB$)]1!, [%(strTempWKB$)]1!) method:=row ow:=[%(strPWKB$)]1!; // 追加
                win -c %(strTempWKB$); // 追加されたワークシートを削除
        }
        else
                continue;
}

dataset sps = {4,1};
dataset sodr = {1,1};
wsort nestcols:=sps order:=sodr; // 追加ワークシートをZ(高さ)でソート
colmove rng:=col(4) operation:=left; // Z列を移動して3番目の列にする

wks.col1.lname$="X";
wks.col2.lname$="Y";
wks.col3.lname$="Z";
wks.col4.lname$="Intensity";
page.longname$= "XYZI Table";
page.title=1; // 名前付け

行列を正規化

内部的には、Origin'x 行列は1次元のベクトルのような配列です。そのため、実行される数学演算は、真の行列ではなくベクトルの演算に似ています。

// 行列を作成
newbook mat:=1;
mdim cols:=10 rows:=10;
msetvalue formula:="rnd()";

//  [0, 1]に正規化
vnormalize ix:=mat(1) method:=range ox:=<input>;