删除特定条件下的冗余测量值的脚本存在问题我有一个数据表,由多行串联的单独测量组成,在执行表拆分功能之前我正在修剪这些数据表,但是我遇到了一些冗余测量的问题,我想删除它们,但当前的代码我我的使用速度非常慢,而且对于我的需要来说可能效率低下。
背景信息:
- 每行都是对连续执行的一块材料进行单独自动测量的结果,并生成包含以下列的报告:
- 分配给每件材料的唯一零件 ID [ PartID ]
- 与用于创建单件材料的原材料关联的批次 ID [ LotID ]
- 执行测量的实际测量值 [ 值 ]
- 根据测量值分配测量结果(通过/失败/返工)[结果]
- 测量时间戳 [ Date_Created ]
我的设备对每件材料生成数十行测量结果,并根据报告处理数千件材料 - 然后将这些报告作为我的原始数据表输入到 JMP 中。每个报告还包含多个批次,因此数据表有多个对“PartID = 1”的引用,因为每个批次都给出了从 1 开始的序列号,因此我需要使用 PartID 和 LotID 来引用给定的材料。在结果为“返工”的情况下,测量设备停止对该单独材料片的任何进一步测量,重新调整该材料片的方向,并将其返回到生产线的起点,重新测量该材料片上的所有先前测试。材料,但仍保留与该材料相关联的相同唯一零件 ID。
期望的结果:
我想使用脚本来遍历数据表并消除直到(并包括)返工结果的所有测量,因为返工后所有测量都会重复,并且返工可能会影响测量值。为此,我当前使用 JSL 脚本循环遍历每一行并执行以下操作:
- 判断结果是否为“返工”;如果是这样,请执行以下操作:
- 将给定材料的 PartID 标识为“xPartID”
- 将给定材料的 LotID 标识为“xLot”
- 将给定测量的 Date_Created 标识为“xDate”
- 选择并删除 (PartID = xPartID) 和 (LotID = xLot) 以及 (Date_Created <= xDate) 的所有行
- 如果结果不是“返工”,则跳出循环,无需继续。
我的速度一直非常慢,基本上代码会导致程序崩溃。如果我一步步运行它,它似乎可以工作,但如果继续运行它最终会死掉。 这是实际的代码:
//Recoding the two potential "Rework" results into a shared value "aRework"; putting the letter "a" in front of it so if I sort by the column ascending then all of these values are at the start of the list, to hopefully make it easier and faster to process them.
dt << Recode Column(
dt:result,
{Map Value(
_rcOrig,
{"FailOnHighRework", "aRework",
"FailOnLowRework", "aRework"},
Unmatched( _rcNow )
)},
Update Properties( 1 ),
Target Column( :result )
);
//Sorting the table using the result column after the recode, so all of the rework rows are at the start of the table
SortColumn = "result";
dt << Sort( By( :result ), Replace Table, Order( Ascending ), Suppress formula evaluation( 1 ) );
//now run the row-by-row script
dt << begin data update;
for each row(
If( :result == "aRework",
xRow = Row();
xPartID=:PartID[Row()];
xLot=:lot[Row()];
xDate=:date_created[Row()];
dt <<SELECT where=""></SELECT>我使用的是 JMP 16.2.0 (570548)。
大规模定制回复:删除特定于某些条件的冗余测量值的脚本存在问题这是脚本的一个版本,在处理 dt 中每 100 行后打印出来
dt = Current Data Table();
dt << select where( :result == "aRework" );
dt2 = dt << subset( selected rows( 1 ), selected columns( 0 ) );
// Remove aRework rows from original table
dt << delete rows;
// Loop across the aRework table and delete rows in orininal table
//dt << begin data update;
start = 1;
end = 0;
alldt2 = N Rows( dt2 );
While( N Rows( dt2 ) > 100,
TotalRows = N Rows( dt2 );
If( TotalRows > 100,
TotalRows = 100
);
end = end + TotalRows;
For( i = 1, i <= TotalRows, i += 1,
dt << select where(
dt:partid == dt2:PartID[i] & dt:lot == dt2:Lot[i] & dt:date_created <= dt2
:Date_created[i]
);
If( N Rows( dt << get selected rows ) > 0,
dt << delete rows
);
);
//dt << end data update;
dt2 << delete rows( 1 :: 100 );
Show(
"Rows " || Char( start ) || " to " || Char( end ) || " of " || Char( alldt2 ) ||
" processed"
);
);
Close( dt2, nosave );
您还可以将其设置为仅处理 x 行,然后重新运行它以处理更多行。
回复:删除特定于某些条件的冗余测量值的脚本存在问题你好,
该脚本似乎按预期工作,并且当针对非常小的数据集(总共 10k 行)运行时,它似乎又好又快,但是我正在使用的实际数据集(160 万行)的速度明显减慢)这样我就无法判断它是否正在杀死程序(没有响应,让它运行了大约 1.5 小时,它似乎仍在运行,但进程没有响应,最终不得不通过任务管理器“结束任务”) - 关于如何改进有什么建议吗?运行 10k 行可能需要 < 10 秒,所以我希望对于 160 万行,如果线性扩展,可能需要 30 分钟,但情况似乎并非如此。
我正在上传数据表的清理子集,以供参考保存到数据表的建议脚本改进。清理后的表仅存在一个 LotID,但通常情况并非如此,只是为了最小化上传文件的总大小。
这是我尝试针对该表运行的脚本的当前版本:
dt = current data table();
dt << select where( :result == "aRework" );
dt2 = dt << subset( selected rows( 1 ), selected columns( 0 ) );
// Remove aRework rows from original table
dt << delete rows;
// Loop across the aRework table and delete rows in orininal table
dt << begin data update;
TotalRows=N Rows(dt2);
For( i = 1, i <= N Rows( dt2 ), i+=1,
dt << select where(dt:partid == dt2:PartID[i] & dt:lot == dt2:Lot[i] & dt:date_created <= dt2:Date_created[i]);
If( N Rows( dt << get selected rows ) > 0,
dt << delete rows
);
);
dt << end data update;
close( dt2, nosave );
再次非常感谢您的帮助!
回复:删除特定于某些条件的冗余测量值的脚本存在问题您好,谢谢!
我现在正在针对我的数据表运行脚本;我认为您在迭代表上的行方面绝对是正确的,该表正在主动将行视为已删除,这可能会扰乱循环逻辑。
我现在正在针对我的数据表运行代码并将报告回来。我还将尝试看看是否可以清理数据表的一些片段,以便将其包含在这篇文章中。非常感谢您的帮助!
回复:删除特定于某些条件的冗余测量值的脚本存在问题我相信您遇到了一个问题,您正在使用 For Each Row 循环数据表,并且通过删除行不断更改正在循环的表,并且循环变得混乱。
这是一段未经测试的代码,我认为它可以消除该问题并且应该运行得相当有效。
Names Default To Here( 1 );
//Recoding the two potential "Rework" results into a shared value "aRework"; putting the letter "a" in front of it so if I sort by the column ascending then all of these values are at the start of the list, to hopefully make it easier and faster to process them.
dt << Recode Column(
dt:result,
{Map Value( _rcOrig, {"FailOnHighRework", "aRework", "FailOnLowRework", "aRework"}, Unmatched( _rcNow ) )},
Update Properties( 1 ),
Target Column( :result )
);
dt << select where( :result == "aRework" );
dt2 = dt << subset( selected rows( 1 ), selected columns( 0 ) );
// Remove aRework rows from original table
dt << delete rows;
// Loop across the aRework table and delete rows in orininal table
For( i = 1, i <= N Rows( dt2 ), i++,
dt << select where(
(dt:partid == dt2:PartID[i] & dt:lot == dt2:Lot[i] & dt:date_created <= dt2:Date_created[i]);
If( N Rows( dt << get selected ) > 0,
dt << delete rows
);
)
);
close( dt2, nosave );
我没有可以使用的示例数据表,因此代码未经测试,但该方法应该允许您修复任何问题并使其正常工作。