脚本こんにちは、みんな、
数式またはスクリプトから新しい列を作成したいデータベースがあります。
データベースの概要は次のとおりです。

- 列 T は実行される操作を表します
- 列 X_3 は機能を表します
- op 列はオブジェクトを表します
目標は、同じ「obj」に対して欠陥の合計が行ごとに異なる場合に「ko」と「op」に対応する数値を追加する「評価」列を作成することです(ここでは値は AT に等しい) )。
最後の特徴として、貸借対照表の列は操作数「3061」に対して入力する必要があります。
これはデータベースの概要です。obj 列は「A」ですが、データベースではこの列の値が変わります。
ご回答いただきありがとうございます。
自動化とスクリプト作成Re: スクリプト行 6 の 180 が最後の列に追加されないのはなぜですか? 0 は 1 とは異なります。
(投稿のタイトルは 1 語ではなく、より有益なものを使用する必要があります)
Re: スクリプト行 6 の合計は 0 に等しいためです。 実際、欠陥の合計が値 0 と異なる場合には、「バランス」列の「op」の値が通知されます。
Re: スクリプトそれでは、2 つの行間で値が異なるかどうかを確認する必要があるのでしょうか? それとも、0 以外の :op を含む行に興味があるだけですか?
Re: スクリプト:sumdefault の値が 0 以外の行にのみ関心があると思います。 なぜなら、デフォルト合計の値が 0 の場合、貸借対照表の列には何も取得されないからです。
Re: スクリプトお返事ありがとうございます !
2 つの方法を比較すると、私の場合は 2 番目の方法が適しているように思えます。
これをデータベースに適合させたところ、両方のデータベースで列の形式が同じになり、次のようなエラーが発生しました。

Re: スクリプトエラーメッセージはフランス語なので理解できません。 エラーは最終的に bilan3 列がないことを示している可能性があります。 (無効な添え字があると言われていますが、bilan3 列がないことが原因です。 これは、列がない場合に値を設定しようとすると、dt[input_loc, "bilan3"] が [](1, 0) を返すためです。
Re: スクリプトこれは、「input_loc」変数が空であるためです。 したがって、「貸借対照表 3」列に新しいセルを割り当てることは不可能です。
Re: スクリプト値「3061」(数値ではなく文字) が列「T」から見つかりません。 また、空の input_loc を処理するために実装したチェックも間違っているため、< 0 ではなく < 1 に変更する必要があります。
Re: スクリプトこのスクリプトは両方を実行し、提供された例で動作します。 それが何をするのかを理解して、理解できない部分があるかどうかを尋ねることを強くお勧めします。
Names Default To Here(1);
dt = Open("$DOWNLOADS/AAA.jmp");
dt << New Column("bilan2", Character, Nominal);
dt << New Column("bilan3", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
/* comparing rows */
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
values = dt[object_rows, "SOMME DEFAUT"];
values1 = Remove(values, 1);
values2 = Remove(values, N Items(values));
differences = [0] |/ values1 - values2;
ops = dt[object_rows[Loc(differences != 0)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) < 0,
continue();
,
dt[input_loc, "bilan2"] = Repeat({result_str}, N Items(input_loc));
);
);
/* zeros */
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
values = dt[object_rows, "SOMME DEFAUT"];
ops = dt[object_rows[Loc(values)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) < 1,
continue();
,
dt[input_loc, "bilan3"] = Repeat({result_str}, N Items(input_loc));
);
);

編集: if ステートメントを変更しましたIf(N アイテム(input_loc) ... < 0 ~ < 1
Re: スクリプトデータベースでは、同じ種類のオブジェクトに対して :T 列の値が昇順に並んでいるとは限りません。 これは、要素が昇順に配置された別の :OPE 列です。 :T 列と :OPE 列は密接に関連しており、オブジェクトの種類ごとに一意です。
値 3061 に対応する :OPE 値よりも低い :OPE は、貸借対照表の列に何も入れるべきではありません。
:OPE の値が、値 3061 に対応する :OPE の値より大きい場合、最初のメッセージですでに説明されている操作が実行されます。
例として以下の漫画を参照してください。

ご回答ありがとうございます!!
Re: スクリプト:OPE 値のチェックを追加します。 行の:OPE 値が「3061」の:OPE 値より小さい場合は無視します。 異なるインデックスと行を追跡するのは少し難しいかもしれませんが、デバッグ出力を追加するとこれが役に立ちます。 また、1 つのオブジェクトに複数の「3061」が存在する可能性がある場合、計算はより複雑になります。
Re: スクリプトはい、あなたの言いたいことは分かりました!
次のようなものを想像します。
If( col = Loc(dt[Row(), :OPE] < Loc(dt[Row(), :T=="3061")),
continue();
,
script...
);
一方、同じオブジェクトが 3061 という番号を 2 回持つことは不可能です。
Re: スクリプトうまくいきません。どうすればそのようなスクリプトを作成できるか知っていますか? @jthi (最後に行うべきチェック)?
ご助力に改めて感謝申し上げます。
Re: スクリプトunique_object のすべての :OPE 値を取得してから、3061 行の :OPE 値を取得します。 その後、すべての :OPE 値のリストから、3061 の :OPE 値よりも大きいインデックスを確認します (Loc() でこれを行うことができます)。
Re: スクリプトそう、私はそう自分に言い聞かせました。そのようなことを考えましたが、変数 a と b を定義するのは依然として困難です。
dt = current data table();
b = // all values :OPE for unique_object
a = // values :OPE for 3061
test = Loc(dt[Row(), b]) > Loc(dt[Row(),a]);
If( test=0 ,
continue();
,
script...;
);
Re: スクリプト特定の一意のオブジェクトの :SOMME DEFAUT 値を格納する値変数に使用されるのと同様のメソッド
values = dt[object_rows, "SOMME DEFAUT"];
デバッグ出力を追加し、オブジェクトを 1 つだけ使用してスクリプトを 1 行ずつ実行してみてください。
Re: スクリプトはい、ありがとうございます。必要な情報を取得できるように、次のようなコードを書きました。
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects);
b = dt[object_rows, "OPE"];
show(b);
a = dt << Get Rows Where( :T == "3061");
valeurs_OPE = :OPE[a];
show(valeurs_OPE);
valeurs_OPE_3061_obj = dt[unique_objects, "valeurs_OPE"];
show(valeurs_OPE_3061_obj);
);ただし、タスク 3061 に対応する OPE 値を obj (変数 "valeurs_OPE_3061_obj") で取得できません。
「valeurs_OPE」変数のみが、タスク 3061 に対応するすべての OPE データを収集します。
Re: スクリプト(今のところは) For Each を無視した方がテストが簡単です。 このようなものから始めてください
Names Default To Here(1);
// dt = Open("$DOWNLOADS/AAA.jmp");
// dt = Current Data Table();
dt = New Table("AAA(1)",
Add Rows(12),
Compress File When Saved(1),
New Column("obj", Character(16), "Nominal", Set Values({"A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "C", "C"})),
New Column("T", Character(4), "Ordinal", Set Values({"3052", "3061", "3082", "3940", "4012", "5010", "2890", "4060", "3061", "3081", "5010", "3061"})),
New Column("OPE", Numeric, "Continuous", Format("Best", 12), Set Values([12, 20, 32, 44, 56, 125, 210, 54, 60, 80, 45, 50])),
New Column("X__3", Character(4), "Nominal", Set Values({"rien", "rien", "incl", "ret", "ret", "rien", "incl", "incl", "ret", "incl", "ret", "rien"})),
New Column("SOMME DEFAUT", Numeric, "Continuous", Format("Best", 12), Set Values([0, 0, 1, 2, 1, 0, 2, 1, 2, 1, 1, 0])),
New Column("op", Character(12), "Nominal", Set Values({"40", "32", "55", "212", "510", "180", "2100", "2240", "2100", "500", "", ""})),
New Column("correct", Character, "Nominal", Set Values({"", "ko - 55 / ko - 212 / ko - 510 / ko - 2100", "", "", "", "", "", "", "ko - 500", "", "", "."}))
);
dt << New Column("bilan", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
unique_object = unique_objects[2];
object_rows = Loc(m_obs, unique_object);
input_loc = Loc(dt[object_rows, "T"], "3061"); // location of 3061 for unique_object
show(input_loc); // index within object_rows
show(object_rows[input_loc]); // real row number
opes = dt[object_rows, "OPE"]; // all OPE values for unique_object
valid_ope_idx = Loc(...//Re: スクリプト
次のスクリプトを続けました。
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
show(value_OPE_3061);
//valid_ope_idx = Loc(b > value_OPE_3061);<BR /> //show(valid_ope_idx);
For( i = 1, i <= N Items(b), i++,
If(N Items(input_loc) < 1 & b[i] <= value_OPE_3061,
continue();
,
values = dt[object_rows, "SOMME DEFAUT"];
ops = dt[object_rows[Loc(values)], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);
);最初に Loc() 関数を使用して行インデックスを決定しましたが、スクリプトを続行する方法がわかりません。 そこで「For」ループを試してみましたが、結果はまだ正しくありません。 前進するのを手伝ってくれませんか?
ご回答いただきありがとうございました。
Re: スクリプトスクリプトの他の部分が機能するまでは、For Each Row を追加しても意味がありません。 行 9 に正しい値が設定されるまで、私が提供した例を続けることができます (B である unique_objects[2] を使用しているため)。 「3061」行 OPE よりも高い OPE インデックスを取得するには、次のように Loc を使用します。
valid_ope_idx = Loc(opes > opes[input_loc]);
これらは opes 行列内のインデックスであり、データ テーブルの行ではないことに注意してください。 それらを行に戻すには、object_rows が特定の一意のオブジェクトの行を含む行列であるため、これらのインデックスを object_rows とともに使用できます。
Re: スクリプトはい、あなたに賛成です !
私が計算式で見つけた値は正しく、あなたと同じです。
ただし、スクリプトの続きを作成するときにさらに困難があります。
値を返さないといけないので「こー……」 /こ-...» :OPE が :T = 3061 に対応する :OPE より大きい場合、および :DEFAULT SUM が 0 と異なる場合 (例のように)。
Re: スクリプトあなたは同じような考えを続けます
- valid_ope_idx に 0 個以上の項目があるかどうかのチェックを追加
- valid_ope_idx のすべての値を取得する
- 次に、これから 0 より大きい値のインデックスを取得します。
- これで、最終的にこれらの特定のインデックスの値を :op から取得できます (最初に値を行に変換することを忘れないでください)。
- Concat Items() を使用してこれらの値を連結します。
- 正しい行に値を追加します
Re: スクリプト私のテストデータベースでは、次のコードで正常に動作します。
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
Starts With( col_name, "SOMME" )
);
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
show(value_OPE_3061);
valid_ope_idx = Loc(b > value_OPE_3061 & dt[object_rows,somme_col] > 0) ;
show(valid_ope_idx);
if( N items(valid_ope_idx) < 1,
continue();
,
ops = dt[object_rows[valid_ope_idx], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);ただし、私の最終的なデータベースでは、同じオブジェクトに対して値 :T = 3061 が数回表示される可能性があります (一方で、OPE の値は同じです!)。
value_OPE_3061 の値は一意である必要があります (たとえば、 value_OPE_3061 = [ 50 , 50 , 50 ] ではなく、 value_OPE_3061 = [ 50 ] です)。
JMPには配列/リストから重複を削除する機能はありますか?
ご回答いただきありがとうございます。
Re: スクリプト前に、複数の「3061」値が存在することは不可能だと言いましたね。
重複を削除するオプションの 1 つは、Associative Array() を << get キーとともに使用することです (浮動小数点数がある場合は機能しません)。この場合の他のオプションは、Design(<
Re: スクリプトこの部分を追加すると、さらにうまく機能します。
Names Default To Here(1);
dt = current data table();
dt << New Column("BILAN", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
somme_col = Filter Each( {col_name}, dt << Get Column Names( "String", Continuous ),
Starts With( col_name, "SOMME" )
);
dt = current data table();
For Each({unique_objects}, unique_objects,
object_rows = Loc(m_obs, unique_objects); // lignes pour chaque obj
b = dt[object_rows, "OPE"]; // les différentes opé pour chaque obj
show(b);
input_loc = Loc(dt[object_rows, "T"], "3061"); // localiser 3061 pour chaque objet
if( N items(input_loc) < 1,
continue();
,
z = object_rows[input_loc]; // localiser les lignes OPE 3061 pour chaque obj
value_OPE_3061 = :OPE[z]; // valeur de l'ope 3061 pour chaque obj
liste={}; // transformer en liste pour supprimer les doublons
for (i = 1, i <= NRows(value_OPE_3061), i++,
for (j = 1, j <= NCols(value_OPE_3061), j++,
InsertInto(liste, value_OPE_3061[i, j]);
);
);
// supprimer les doublons
if( N items(liste) <= 1,
a = liste;
,
a = Left(liste,1);
);
// repasser en matrice pour faire les comparaisons
Mat_3061 = Matrix(a);
show(Mat_3061);
valid_ope_idx = Loc(b > Mat_3061 & dt[object_rows,somme_col] > 0) ;
show(valid_ope_idx);
if( N items(valid_ope_idx) < 1,
continue();
,
ops = dt[object_rows[valid_ope_idx], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
dt[object_rows[input_loc], "BILAN"] = Repeat({result_str}, N Items(input_loc));
);
);
);実際、あなたは正しいです@jthi 、しかし、私は、:obj の値 3061 に対して、変数 :OPE の異なる値は存在できないと話していました (その後、obj 内で、たとえば、値 :T が 3061 に等しいことが 2 回存在する可能性がありますが、値 :OPE は同じになります)。
最終的に、出力では、同じ :obj に対して 3061 に等しい値 :T が数回存在する場合、表示を繰り返さないようにしたいと考えています。
例 :

次のようなスクリプトを使用します。
input_loc = Loc(dt[object_rows, "T"], "3061");// localiser 3061 pour chaque objet
liste2={}; // transformer en liste pour supprimer les doublons
for (i = 1, i <= NRows(input_loc), i++,
for (j = 1, j <= NCols(input_loc), j++,
InsertInto(liste2, input_loc[i, j]);
);
);
// supprimer les doublons
if( N items(liste2) <= 1,
c = liste2;
,
c = Left(liste2,1);
);
// repasser en matrice pour faire les comparaisons
loc_3061 = Matrix(c);
正しく動作します。 :T に対応する最初のインデックスが 3061 に等しいとします。
ただし、上記のキャプチャのように、同じ行にある重複要素を削除できるようにしたいと考えています。
kb-2203 / kb-2203 --> kb-2203
Re: スクリプトオブジェクトの値 3061 を持つ最初のインデックスを選択するだけです。
Re: スクリプトこのようなものは、私がこれを解決する方法です。 サンプルデータで動作するはずです
Names Default To Here(1);
// dt = Open("$DOWNLOADS/AAA.jmp");
// dt = Current Data Table();
dt = New Table("AAA(1)",
Add Rows(12),
Compress File When Saved(1),
New Column("obj", Character(16), "Nominal", Set Values({"A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "C", "C"})),
New Column("T", Character(4), "Ordinal", Set Values({"3052", "3061", "3082", "3940", "4012", "5010", "2890", "4060", "3061", "3061", "3081", "5010", "3061"})),
New Column("OPE", Numeric, "Continuous", Format("Best", 12), Set Values([12, 20, 32, 44, 56, 125, 210, 54, 60, 60, 80, 45, 50])),
New Column("X__3", Character(4), "Nominal", Set Values({"rien", "rien", "incl", "ret", "ret", "rien", "incl", "incl", "ret", "ret", "incl", "ret", "rien"})),
New Column("SOMME DEFAUT", Numeric, "Continuous", Format("Best", 12), Set Values([0, 0, 1, 2, 1, 0, 2, 1, 2, 2, 1, 1, 0])),
New Column("op", Character(12), "Nominal", Set Values({"40", "32", "55", "212", "510", "180", "2100", "2240", "2100", "2100", "500", "", ""}))
);
dt << New Column("bilan", Character, Nominal);
Summarize(dt, unique_objects = by(:obj));
m_obs = dt[0, "obj"];
For Each({unique_object}, unique_objects,
object_rows = Loc(m_obs, unique_object);
input_loc = Loc(dt[object_rows, "T"], "3061");
If(N Items(input_loc) == 0,
continue();
//Throw("3061 not found");
, N Items(input_loc) > 0,
input_loc = input_loc[1];
);
opes = dt[object_rows, "OPE"];
valid_ope_idx = Loc(opes > opes[input_loc]);
If(N Items(valid_ope_idx) < 1,
result_str = ".";
,
values = dt[object_rows[valid_ope_idx], "SOMME DEFAUT"];
ops = dt[object_rows[valid_ope_idx[Loc(values)]], "op"];
result_str = "ko - " || Concat Items(ops, " / ko - ");
);
dt[object_rows[input_loc], "bilan"] = result_str;
);