大家好,
我正在尝试创建一个公式或脚本,该公式或脚本将根据表中是否存在另一行与使用当前行作为输入的逻辑匹配的值来为每一行设置一个特定的值(“好”、“坏”或“N/A”)。
我有一个脚本,在使用完整数据表的一小部分时,通过使用嵌套 For 循环来实现这一点。但是,当我尝试使用大约 100 万行的完整数据表时,该脚本会使 JMP 崩溃。
有没有更有效的方法可以让 JMP 执行此操作?(或者如果可以使用 SQL 完成,我可以在将其带入 JMP 之前完成此操作)。
请参阅附件中执行我所述操作的脚本。
在处理数据表时,通常不需要嵌套 for 循环。
您能否提供一小部分数据并在其中包含一个包含您想要的结果的列?
好吧,出于隐私原因,我会模拟数据。
| 可乐 | colB | colC | 日期 | 油菜 | 逻辑 |
| A0001 | 16 | 100 | 2022/04/01 上午 9:15:01 | 动作1 | 不适用 |
| A0001 | 100 | 182 | 2022/04/01 上午 9:15:31 | 动作2 | 好的 |
| A0001 | 100 | 100 | 2022/04/01 上午 9:15:36 | 动作一 | 不适用 |
| A0002 | 212 | 200 | 2022/04/02 3:15:21 上午 | 动作一 | 不适用 |
| A0002 | 211 | 282 | 2022/04/02 3:15:11 上午 | 动作2 | 坏的 |
| A0002 | 212 | 200 | 2022/04/02 凌晨 3:15:16 | 动作1 | 不适用 |
| A0003 | 441 | 382 | 2022/05/01 上午 1:15:31 | 动作2 | 坏的 |
| A0004 | 441 | 382 | 2022/05/01 5:16:31 上午 | 动作2 | 坏的 |
| A0004 | 441 | 300 | 2022/05/01 5:15:31 上午 | 动作1 | 不适用 |
如果原始脚本的逻辑不清楚:
如果当前行的 colE 是“Action 1”:则分配“N/A”;
否则,如果当前行的 colE 是“Action 2”,则遵循下一段中的逻辑。
如果表中存在另一行,其列 colA 和 colB 的值与当前行的值相同;当前行的 colC 值正好比另一行多 82; colDate 值彼此相差 18 秒以内;当前行的 colE 是“Action 2”,而另一行的 colE 是“Action 1”:然后分配“Good”;否则分配“坏”。
感谢任何帮助! 我现在只是没有看到没有嵌套循环的方法。
但我现在至少意识到我应该在原始脚本的第 25 行之后放置一个 Break()。 如果我已经找到至少一个存在,就没有理由继续寻找符合我的标准的另一行。
这个脚本中的逻辑过于复杂,因为我不知道数据的所有限制(例如可以有多个匹配项)并且我没有优化它
Names Default To Here(1);
dt = New Table("Untitled",
Add Rows(9),
Compress File When Saved(1),
New Column("colA", Character, "Nominal", Set Values({"A0001", "A0001", "A0001", "A0002", "A0002", "A0002", "A0003", "A0004", "A0004"})),
New Column("colB", Numeric, "Continuous", Format("Best", 9), Set Values([16, 100, 100, 212, 211, 212, 441, 441, 441])),
New Column("colC", Numeric, "Continuous", Format("Best", 9), Set Values([100, 182, 100, 200, 282, 200, 382, 382, 300])),
New Column("colDate",
Character(22),
"Nominal",
Set Values(
{" 2022/04/01 9:15:01 AM", " 2022/04/01 9:15:31 AM", " 2022/04/01 9:15:36 AM", " 2022/04/02 3:15:21 AM", " 2022/04/02 3:15:11 AM",
" 2022/04/02 3:15:16 AM", " 2022/05/01 1:15:31 AM", " 2022/05/01 5:16:31 AM", " 2022/05/01 5:15:31 AM"}
)
),
New Column("colE",
Character(16),
"Nominal",
Set Values({"Action1", "Action2", "Action1", "Action1", "Action2", "Action1", "Action2", "Action2", "Action1"})
),
New Column(" Logic", Character(16), "Nominal", Set Values({" N/A", " Good", " N/A", " N/A", " Bad", " N/A", " Bad", " Bad", " N/A"}))
);
dt << New Column("Group", Character, Nominal, << Set Each Value(char(:colA)||char(:colB)));
//fix date
Column(dt, "colDate") << Set Each Value(Substitute(:colDate, " AM", "")) << Data Type(Numeric);
dt << New Column("Logic", Character, Nominal, << Set Each Value(
As Constant(
m_group = :Group << get values;
m_c = :colC << get values;
m_date = :colDate << get values;
);
If(:colE == "Action1",
"N/A";
, :colE == "Action2",
cur_group_idx = Loc(m_group, :Group);
If(N Items(cur_group_idx) == 0,
"Bad"
,
plus_idx = cur_group_idx[Loc(:colC - 82 == m_c[cur_group_idx])];
If(N Items(plus_idx) == 0,
"Bad"
,
timediff_idx = Loc(Abs(m_date[plus_idx] - :colDate) <= 18);
If(N Items(timediff_idx) > 0,
If(:colE == "Action2" & :colE[timediff_idx[1]] == "Action1",
"Good"
,
"Bad"
)
,
"Bad"
);
)
);
,
"Bad";
);
));
dt << Delete Column("Group");
