刪除特定條件下的冗餘測量值的腳本有問題我有一個數據表,由多行串聯的單獨測量組成,在執行表拆分功能之前我正在修剪這些數據表,但是我遇到了一些冗餘測量的問題,我想刪除它們,但當前的代碼我我的使用速度非常慢,而且對我的需要來說可能效率低。
背景資訊:
- 每行都是對連續執行的一塊材料進行單獨自動測量的結果,並產生包含以下列的報告:
- 分配給每件材料的唯一零件 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 );
我沒有可以使用的範例資料表,因此程式碼未經測試,但該方法應該允許您修復任何問題並使其正常工作。