
スケーリングされた応答オーバーレイグラフを使用した複数のY軸
止まる! スクリプトが必要な場合は、投稿の下部に添付されています。
これは、すべてのy軸変数をスケーリングしてオーバーレイし、変数の単位と範囲でy軸スケールを提供する特殊なグラフです。 これは、すべて異なる範囲にある3つまたは4つの変数をオーバーレイする場合に役立ちます。 上の図では、流量は0〜40の範囲にあり、電力は200〜1000および100〜500の範囲にあります。 このタイプのグラフは、複数のセンサーが同時にデータを記録している科学および工学アプリケーションでよく使用されますが、各センサーの範囲はまったく異なります。 たとえば、発酵の例では、グルコースは1〜5 g / dl、pHは6.8〜7.8、乳酸は10〜50ミリモル、細胞数または生存率は1桁大きくなります。 時間の経過に伴うすべての変数間の関係をグラフ化する簡単な方法は、プロセスの反応速度を理解する(または異常なパターンを検出する)のに非常に役立ちます。
この特定のグラフは、かなり前から私の宿敵でした。 適度に見栄えのするものを取得するには、通常、JMP内またはPowerPoint内でクリエイティブなコピーと貼り付けが必要です。 では、なぜこのグラフはそれほど難しいのでしょうか。 どういうわけか、データをスケーリングして1つのグラフに結合してから、スケーリングされていないすべてのy軸コンポーネントをスケーリングされたデータグラフと結合する必要があります。 私が見て試したすべての方法は、コピーと貼り付けの手順が非常に多く、Powerpointでグラフ要素のグループ化と再フォーマットを行う方法では、すべての要素を正しく整列させるのが面倒なため、結果が悪くなることがあります。私のスライドに。 面倒で、手動で、退屈で、反復的なプロセスは、JSLの自動化を叫びます。
ソリューションをスクリプト化するための戦略を考える際には、考慮すべきいくつかのステップがあります
1.変数/列ごとにy軸ボックスを作成します。
2.各列の値を同じ範囲にスケーリングします
3.オーバーレイプロットで機能するようにデータの形状を変更します。
4. yロールとxロールの列を選択するための起動ダイアログがあれば(または単に行番号を使用して)、それもいいでしょう。
5.最後になりましたが、グラフには、元のスケールの各変数を含む軸ボックスを含める必要があります。
私はJSL鉛筆を削り、このフィギュアの自動作成を試みました。 ここで私が何をしたかを説明しようと思います。それをより機能的にする方法についてさらに議論していただければ幸いです。 現在の状態は、1つのタイプの固定図形を生成できるスクリプトであり、残された中間テーブルのウェイクをクリーンアップする必要はありません。 (完全なスクリプトを投稿に添付します)
最初のステップ:起動ダイアログ
cd = Column Dialog(
ylist = ColList( "Y", Min Col( 2 ), Max Col( 8 ), Data Type( "Numeric" ), Modeling Type( {"Continuous"} ) ),
xlist = ColList( "X", Max Col( 1 ), Modeling Type( {"Continuous", "Multiple Response"} ) )
);
Eval( Eval Expr( cd[1] ) ); //eval expr, returns what is in cd[1], and the eval makes it execute
Eval( Eval Expr( cd[2] ) ); //separately run just cd[1], then run evalexpr)cd[1], this is how I get the ylist and xlist variables
起動ダイアログを書き始めるときはいつでも、スクリプトインデックスから恥知らずにそのダイアログをコピーし、不要なものを削除するか、必要に応じて追加します。 目標は、YとXをキャプチャすることです。 ここにはいくつかのルールがあります。たとえば、列は数値で連続している必要があり、少なくとも2つのYが必要です(この理由は後で詳しく説明しますが、Yが1つしかない場合は、なぜこれを使用するのですか? ?)8 Y応答の制限もあります。これを自由に編集してください。8を超えると、面倒に見えます。
eval(eval expr())の最後の2行は、列ダイアログの「cd」で返されたものからylist変数とxlist変数を生成する方法です。
データテーブル1:標準化されたデータテーブル
dt1 = New Table( "multiple y-axis table" ); //this is the table where the standardized values go
If( N Items( xlist ) == 1, //note that if there is a column selected for xlist, then it doesn't get scaled
Insert Into( ylist, xlist, 1 ), //call me crazy, but the first value in ylist is the "X", if it exists
dt1 << New Column( "Row", formula( Row() ) )
);
DT1は、標準化された後のデータを含むテーブルです。 ダイアログでXが選択されていない場合、最初の列は「行」であり、グラフのX軸として使用する行番号が含まれています。 Xがある場合は、ylistの最初の位置に追加されます。 はい、そうです。変数ylistにはXとYの両方があります。
dt1を埋めて「軸ボックス」を作成する
For(
<FONT color="#FF6600"> If( N Items( xlist ) == 1, //yep, that's an "if" argument inside a "for" loop
i = 2; //if an "x" is specified, then start with the second thing in the list
ycol = As Column( dt, ylist[1] ) << get values;
dt1 << New Column( Munger( ylist[1], 1, ":", "" ), set values( ycol ) );//this is soooo ugly
,i = 1), i <= N Items( ylist ), i++, //end of setup for the For loop</FONT>
<FONT color="#008000"> ycol = As Column( dt, ylist[i] ) << get values;
yycol = ((ycol - Min( ycol )) / (Max( ycol ) - Min( ycol )));
dt1 << New Column( Munger( ylist[i], 1, ":", "" ), set values( yycol ) ); //this is soooo ugly, very sorry</FONT>
<FONT color="#0000FF"> amin = Min( ycol ); //this second part of this script is getting values to make the y-axis boxes
amax = Max( ycol ); //I need the min and max values from each of the unscaled columns, along with their names
ymin = amin - ((amax - amin) * .1); //The y-axis box axis range is 10% higher and lower than the min and max.
ymax = amax + ((amax - amin) * .1); //It looks better and is more closely aligned with the scaled data in gb
obj1 = Graph Box( Framesize( 0, 230 ), yName( Char( ylist[i] ) ), Y Scale( ymin, ymax ) ); </FONT><BR /><FONT color="#0000FF"> //its not a true axis box, just a squished graph box. the axis box was free
Insert Into( objhlb1, Name Expr( obj1 ) ); </FONT><BR /><FONT color="#0000FF"> //there is a lot of inserting of name expr() here. its part of building expressions from the inside out.</FONT>
);
この次の部分は、Y用に選択された列のリストをループします。 Xが指定されている場合は、リストの2番目の項目から始まります
最初の部分では、ループを設定し、結果のテーブルを作成するためのロジックを使用します。 テーブルバリアントは、x軸変数が指定されているかどうかによって異なります。
スクリプトの中央部分は、短くても非常に重要です。 元のテーブル(dt)の各列から値を取得し、スケーリングされた値をdt1に入れます。私はこの行を本当に誇りに思っていません:dt1 <<新しい列((ムンゲール(ylist [i]、 1 、 ":" 、 "" )、値を設定します(yycol));しかし、これが問題です。新しい列には「colname」またはcolnameが必要であり、:colnameはこのステップを強制終了するため、コロンを削除しました。 (コメントでこれを行うためのより良い方法を送ってください。)
最後の部分では、列の値の各セットを調べ、それらを使用してグラフボックスをスケーリングしました。 グラフボックスは素敵な軸ボックスになります。グラフボックスの幅が0に設定されている場合、y軸ボックスのみが表示されます。 何が起こるかというと、このステップはグラフをフォーマットするために重要です。 最後の行は、グラフボックスの式を、最後に評価される表示ボックスに挿入します。 name exprを使用してobj1(グラフボックス)を参照することにより、スクリプトを作成してスクリプト内のすべての変数を評価しますが、スクリプトは評価されません。 各グラフボックスは、水平リストボックス(objhlb1)に挿入されます。 後でこのボックスは別のボックスに挿入されます。
グラフを作成するためのテーブルの作成:
For(
If( N Items( xlist ) == 1,
i = 2,
i = 1
), i <= N Items( ylist ), i++,
Insert Into( dt2stackcols, ylist[i] )
);
Insert Into( dt2stack, Name Expr( dt2stackcols ), 1 );
Eval(
Substitute( Expr( dt2 = dt1 << ping ),
Expr( ping ), Eval Expr( dt2stack )
)
); //This is tricky!
dt2 << set name( "multiple y-axis stack" );
上記で制約について述べました。少なくとも2つのy変数を選択する必要がありました。 変数を1つだけスタックすることはできず(すでにスタックされているため)、1つしかない場合はスクリプトがクラッシュします。 ここで興味深いのは、指定されたXを持つかどうかを処理するロジックです。 Xがある場合、私はすでにそれをスケーリングしたくありませんでした。Xラベルとして使用したいので、スタックに含めたくありません。 Xが指定されていない場合は、ylistのすべての変数を使用します。
赤字の最後の部分は説明が難しいです。 1行で、スタックを実行するためのスクリプトが作成され、実行/評価されます。 「Ping」は置き換えられるパターンであり、これらの表現をバウンスすることを考えていたときに最初に頭に浮かんだ言葉でした。
dt2stackcolsの式はどこにありますか? わかりやすくするために、またこれに取り組んでいたときの正気のために、定義されているすべての式をスクリプトの先頭に移動しました。 スクリプトの順序を変更すると、必要になる前にすべての式が存在していたため、これは役に立ちました。 スクリプトに散らばったままにしておくと、スクリプトの後半で定義された式に挿入しようとすることがよくあります。 添付されている完全なスクリプトを見て、これがどのようにレイアウトされているかを確認してください。 これはベストプラクティスではないかもしれませんが、ネミシスグラフのすべてのストップを引き出しています。
すべての部品を組み立てる
Insert Into( objout, Name Expr( objhlb1 ) );
Insert Into( objvlb, Name Expr( objout ) );
Insert Into( objhlb2, Name Expr( objvlb ) );
Insert Into( objhlb2, Name Expr( obj ) );
Insert Into( objwin, Name Expr( objhlb2 ) );
Eval( Eval Expr( objwin ) ); //Evaluating all the assembled parts after all the expressions are evaluated
gb << size( 600, 285 ); //if you want to format the graph, send messages to gb
JSLの最も優れている点の1つは、関数ベースの言語であるということです。 これにより、2つの重要なことが達成されます。1つは、車輪の再発明をしなくても特定のことを簡単に実行できること、もう1つは、複雑な構造を構築する方法を簡単に考えることです。 (あなたがそれらをあなたが裏返しに構築しているタマネギとして考える限り。 たとえば、典型的な考え方は次のようになります。 最初にたくさんの土地を購入し、次にその土地に建物を建て、次にその建物に部屋を置き、次に部屋にオフィスチェアなどを置き、次に椅子に座って、最後に働き始めます。 関数思考はこのように機能します。最初に椅子があり、私はそれにバイロンを入れました。 それから私は椅子(まだバイロンを持っています)をオフィスに置き、それを建物に入れ、それを区画に入れ、それを購入し、最後にバイロンが働きます。
最初のステップは、グラフボックスをobjhlb1に配置することでした。次に、アウトラインボックス(objout)とobjhlb1が挿入される垂直リストボックス(objvlb)があります。 これはグラフの左側です。 左側にあるため、ovjvlbは2番目の水平リストボックス(objhlb2)に挿入され、次にグラフビルダーチャート(obj)が挿入されます。 最後に、objhlb2(現在はすべてが含まれています)が新しいウィンドウボックスに挿入され、表示できるようになります。 そして、それをすべて機能させるために、それは評価されます。 Evalを使用したばかりの場合は、.. 何が起こるかわかりませんが、機能しません。最初にEval Exprを実行して、評価されたすべてのスクリプト全体が表示されるようにしました(スクリプトでEval Expr(objwin)だけを実行して、意味を確認してください)。 Evalを使用してその部分を実行しました。
グラフビルダーのプロットであるobjのフォーマットが少しあります。 タイトルがオフになり、フレームサイズが再調整され、y軸がオフになります。 これは、y軸ボックスのスケールと形状に一致させるためのすべてです。 x軸を編集でき、凡例を移動でき、すべてのGBオプションをさらにフォーマットできるため、グラフビルダープロットを使用すると便利です。
現在のエンドポイント
スクリプトが立っているように、7番目のメジャーリビジョンでは、あまり整頓されておらず、たくさんのテーブルがぶら下がっています。 それと他のいくつかのことを修正する必要があります。 ですので、追加のアイデアがあれば、一緒に送ってください。 何かが起こらないだけです。たとえば、グラフのデータは元のデータテーブルに動的にリンクされず、Y軸ボックスは[スケーリングされた応答グラフのアウトライン]ボックスにリンクされないため、サイズを変更する必要があります。それぞれ独立して。 それがうまくいけば素晴らしいでしょう。 最後に、スクリプトを壊したり、不幸な結果を返したりする方法があるとほぼ100%確信しているので、特別な列名や極端な外れ値、または多くの欠落データに注意してください。
このスクリプトを機能させるためのより良い方法についてのコメントが欲しいです。 (動作について言えば、これをPCとMacのv13とv14でテストしたところ、投稿に問題なく動作しました。)
著者からのエンドノート:
これは、私たちがこれについて話しているかのように、最も非公式な口調で書かれています。
コーディングの正式な専門用語であるIMHOがコミュニケーションを妨げるため、これは意図的なものです。 代わりに、私は難読化を避けます。