脚本大家好,
我有一个数据库,我想在其中从公式或脚本创建一个新列。
以下是数据库的概述:

- 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;
);