腳本大家好,
我有一個數據庫,我想在其中從公式或腳本創建一個新列。
以下是數據庫的概述:

- T 列代表要執行的操作
- X_3 列代表一個特徵
- op列代表對象
目標是創建一個“評估”列,當同一“obj”的缺陷總和從一行到另一行不同時,我們在其中添加“ko”和與“op”對應的數字(此處值等於 AT )。
最後一個特殊性是,資產負債表欄必須填寫操作數“3061”。
這是數據庫的概述,列 obj 是“A”,但在數據庫中該列會更改值。
謝謝您的回答 !
自動化和腳本編寫回复:腳本為什麼沒有將第 6 行操作 180 添加到最後一列? 0 與 1 確實不同。
(您應該使用更多信息性的帖子標題,而不僅僅是一個詞)
回复:腳本因為第 6 行的總和等於 0。 事實上,當缺陷總和不同於值0時,則通知“餘額”列中“op”的值。
回复:腳本那麼是否需要檢查兩行之間的值是否不同? 或者您只是對 :op 不為 0 的行感興趣?
回复:腳本我認為我們只能對 :sum default 的值不為 0 的行感興趣。 因為當:default sum 的值為 0 時,資產負債表欄中什麼也得不到。
回复:腳本由於錯誤消息是法語,我無法理解。 錯誤最終可能是告訴您沒有 bilan3 列。 (這是說存在無效下標,但這是由於沒有 bilan3 列引起的。 這是因為如果您沒有該列,然後嘗試為其設置一些值,則 dt[input_loc, "bilan3"] 將返回 [](1, 0)。
回复:腳本這是因為“input_loc”變量為空。 因此,對於“資產負債表3”列中的新單元格的分配是不可能的。
回复:腳本從“T”列中找不到值“3061”(字符,而不是數字)。 另外,我實現的處理空 input_loc 的檢查不正確,您應該將其修改為 < 1 而不是 < 0。
回复:腳本該腳本同時執行這兩項操作並適用於提供的示例。 我強烈建議您嘗試了解它的作用,並詢問是否有某些部分您不明白。
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語句如果(N 項(input_loc) ...從 < 0 到 < 1
回复:腳本在數據庫中,對於同一類型的對象,:T 列的值不一定按升序排列。 這是另一個 :OPE 列,其元素按升序排列。 :T 和 :OPE 列密切相關,它們對於每種類型的對像都是唯一的。
低於 3061 對應的 :OPE 值的 :OPE,不應在資產負債表欄中添加任何內容。
當 :OPE 的值大於對應於值 3061 的值 :OPE 時,將執行第一條消息中已描述的操作。
請參閱下面的漫畫作為示例:

謝謝您的回答 !!
回复:腳本添加對 :OPE 值的額外檢查。 如果行的 :OPE 值低於“3061”的 :OPE 值,則忽略它。 跟踪不同的索引和行可能有點困難,但添加調試打印有助於解決此問題。 另外,如果一個對象可以有多個“3061”,計算就會變得更加複雜。
回复:腳本是的,我明白你的意思!
我想像的東西看起來像這樣:
If( col = Loc(dt[Row(), :OPE] < Loc(dt[Row(), :T=="3061")),
continue();
,
script...
);
另一方面,同一個對像不可能有兩次數字 3061。
回复:腳本它不起作用,你知道我怎樣才能製作這樣的腳本嗎@jthi (最後要做的檢查)?
再次感謝你的幫助 !
回复:腳本獲取 unique_object 的所有 :OPE 值,然後獲取 3061 行的 :OPE 值。 之後,從所有 :OPE 值列表中檢查高於 3061 :OPE 值的索引(Loc() 可以執行此操作)。
回复:腳本是的,這就是我對自己說的,我想到了類似的事情,但困難仍然是定義變量 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...;
);
回复:腳本與用於存儲特定唯一對象的 :SOMME DEFAUT 值的值變量類似的方法
values = dt[object_rows, "SOMME DEFAUT"];
添加調試打印並嘗試僅使用一個對像一次運行腳本一行
回复:腳本是的,謝謝,我寫了一個這樣的代碼,它允許我獲得我需要的信息:
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);
);但是,我無法通過:obj(變量“valeurs_OPE_3061_obj”)獲取任務3061對應的OPE值。
只有變量“valeurs_OPE”收集與任務 3061 對應的所有 OPE 數據。
回复:腳本如果您(暫時)忽略 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(...//回复:腳本
我繼續執行以下腳本:
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”循環,但結果仍然不正確。 你能幫助我前進嗎?
預先感謝您的所有回复!
回复:腳本在腳本的其他部分正常工作之前,添加 For Each Row 是沒有意義的。 您可以繼續使用我提供的示例,直到將正確的值設置為第 9 行(由於使用了 unique_objects[2],即 B)。 要獲得高於“3061”行 OPE 的 OPE 索引,您可以像這樣使用 Loc 。
valid_ope_idx = Loc(opes > opes[input_loc]);
請注意,這些是操作矩陣中的索引,而不是數據表中的行。 要將它們轉換回行,您可以將這些索引與 object_rows 一起使用,因為 object_rows 是一個矩陣,其中包含特定唯一對象的行
回复:腳本是的,我同意你的觀點!
我用我的公式找到的值是正確的,我發現和你一樣。
然而,在劇本續集的構建上,我遇到了更大的困難!
因為我必須返回值“ko-..... /ko-...» 當 :OPE 大於 :OPE(對應於 :T = 3061)並且 :DEFAULT SUM 不為 0 時(如示例中所示)。
回复:腳本他們你繼續類似的想法
- 添加檢查 valid_ope_idx 中是否有超過 0 個項目
- 獲取 valid_ope_idx 的所有值
- 然後從中獲取大於 0 的值的索引
- 然後你終於可以從 :op 獲取這些特定索引的值(記住首先將它們轉換為行)
- 使用 Concat Items() 將這些值連接在一起
- 將值添加到正確的行
回复:腳本在我的測試數據庫中,使用以下代碼可以正常工作:
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 上是否有函數可以從數組/列表中刪除重複項?
謝謝您的回答 !
回复:腳本我想之前你說過不可能有多個“3061”值?
刪除重複項的一種選擇是使用帶有 << 獲取鍵的 Associative Array() (如果有浮動則不起作用),在這種情況下的其他好處是使用 Design(<
回复:腳本我添加了這部分,效果更好:
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 中可以有 2 次,例如值 :T 等於 3061,但值 :OPE 將相同)。
最後,在輸出中,當同一個 :obj 的值 :T 多次等於 3061 時,我希望顯示不重複。
例子 :

使用這樣的腳本:
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
回复:腳本您可以只選擇該對象的第一個索引值為 3061 的索引。
回复:腳本像這樣的事情就是我解決這個問題的方法。 應該使用示例數據
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;
);