「獲取行」的時間太長我有一個參考表,其中每一列都是主資料表列的名稱,而行中的值是主表中該列的錯誤資料的部件號。例如,在主表中,第 1 列是零件編號,第 2 列是「Temp」。假設行號等於部件號,因此第 1 行是部件“1”,並且假設“Temp”列中的值為 65。第 2 部分的溫度為 -100,因此是壞數據。因此,在名為「Temp」的欄位下的參考表中,第 1 行的值為「2」。對主表中具有錯誤資料的所有零件編號重複此操作,然後對每一列也重複此操作。
這給了我一個錯誤的資料引用表,然後我可以循環遍歷以在每次為主表提取最新資料時自動刪除錯誤資料。我有有效的程式碼,但是行:
(其中 vlist 包含參考表中的所有零件號,dt2 是主資料表)
try(rowindex=dt2 << Get Rows Where(contains(vlist,:WORKORDERNO )));
超慢。完成需要 22 秒。由於我有 196 個專欄要瀏覽,這需要很長時間。任何有關如何加快速度的建議將不勝感激!
完整程式碼在這裡:
names default to here(1);
dt=open("J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp", invisible(1)); //this is the reference table
dt<<BEGIN data="https://community.jmp.com/" update=""></BEGIN>自動化和腳本編寫視窗回覆:「獲取行」的時間太長考慮 JMP 將如何進行名稱解析。當你運行一個獲取行Where()函數,它將逐行遍歷表格,評估在哪裡表達。每次評估都需要對定義的所有變數進行名稱解析,並且由於您的影片列表vairable 是在運行循環之外定義的,每次迭代都必須進行一些範圍遍歷,從而導致大量浪費的工作。
為了解決這個問題,請考慮預先評估在整個查找過程中保持不變的任何名稱,如下所示:
Names Default To Here( 1 );
dt = Open(
"J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp",
invisible( 1 )
); //this is the reference table
dt << begin data update;
cols = dt << get column names();
dt2 = Data Table( "Master data pull daily download" ); //this is the main table
dt2 << begin data update;
dt2 << Clear Select();
cols2 = dt2 << get column names();
vlist = {};
For( i = 1, i <= 2 /*N items(cols)*/, i++,
Try( vlist = Column( dt, cols[i] ) << get values );
starttime = Tick Seconds();
Eval( Eval Expr(
Try( rowindex = dt2 << Get Rows Where( Contains( Expr( vlist ), :WORKORDERNO ) ) );
) );
endtime = Tick Seconds();
Print( "run time", Eval Insert( "Analysis took ^round(endtime - starttime)^ seconds" ) );
Try( Column( dt2, cols[i] )[rowindex] = . );
);
dt2 << end data update;
dt << end data update;
Close( dt, nosave );注意評估(評估表達式(... Expr( vlist ) ... ) )表達式-即預評估影片列表因為它在整個循環中是一個常數。
回覆:「獲取行」的時間太長我相信您可以使用 AsConstant(vList) 來達到相同的效果,名稱“vlist”只應為每個 GetRowsWhere 呼叫評估一次。
回覆:「獲取行」的時間太長謝謝回覆@ErraticAttack ,我將您的程式碼修改彈出,程式碼執行時間為 21 秒 vs 22 秒。所以好一點,但不是我需要的地方。任何其他想法將不勝感激!
回覆:「獲取行」的時間太長我還發現,如果您能找到使用 Loc 的方法,在大多數情況下使用 Loc 會更快。 可能有比這更好的方法,但您可以嘗試類似的方法來替換 GetRowsWhere 呼叫。
dt = New Table( "BadTable",
Add Rows( 100 ),
New Column( "BadPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
dt2 = New Table( "FullTable",
Add Rows( 10000 ),
New Column( "NewPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
newPNumbers = dt2:NewPartNumbers<< GetValues;
badPNumbers = AssociativeArray(dt:BadPartNumbers << GetValues);
rowIndex = Loc(Matrix(badPNumbers << GetValues(AsList(newPNumbers))));
我不太確定你的表是如何設定的,但基本上它是將壞零件號碼轉換為關聯數組,其中壞零件號碼返回 1,其他任何東西都會返回 0。 當您將所有部件號的清單傳遞給 GetValues 時,它會為每行傳回由 1 和 0 組成的清單。 對此呼叫 Loc 傳回找到 1 的索引,該索引應對應於具有錯誤部件號的行。
回覆:「獲取行」的時間太長@ErraticAttack因此,我製作了一個測試主資料表和參考表來嘗試共享,以便人們可以一起玩,但是當我這樣做時,腳本運行得非常快,不到一秒鐘。所以現在我想知道這是否與我的實際數據表有關?
這是測試表

回覆:「獲取行」的時間太長根據您的數據,您可以使用許多不同的方法來執行這些檢查(連接/更新、定位、獲取行、關聯數組、匯總表...)。 你的表格有多少行? 您的參考表列中最多有多少個不同的值? 大多數值是否為空(在執行比較之前刪除空值以使清單更小或僅將其包含一次)?
回覆:「獲取行」的時間太長嘿@jthi ,
以下是主表的概述:

這是參考表:

以下是參考表中每列有多少資料:(來自缺失資料篩選器輸出)
號碼缺失
0
0
0
0
3115
6075
12237
16591
16591
16591
16591
16772
17038
17093
17095
17095
17099
17099
17109
17110
17113
21542
22781
23634
24792
24792
25058
25172
25280
25341
25356
25376
25376
25827
25863
25875
25893
25894
25897
25905
25942
25957
25963
25963
25963
25965
25968
25968
25968
25968
26367
26564
27190
27404
27414
27420
27437
27453
27465
27474
27478
27493
27503
27522
27547
27553
27573
27592
27597
27597
27597
27597
27619
27626
27628
27628
27629
27629
27629
27629
因此,由於少數列包含大量錯誤數據,大多數列都充滿了“缺失數據”/空白。
讓我想知道 vlist 中的所有這些空白是否會導致速度變慢:

回覆:「獲取行」的時間太長我懷疑所有的空白都會導致你的程式碼變慢。這是一個解決方法。只需將您建立的 vlist 替換為
Try( vlist = Associative Array( As Column( cols[i] ) ) << get keys );
If( vlist[1] == "",
Remove From( vlist, 1, 1 )
);
回覆:「獲取行」的時間太長它很可能會導致速度變慢,尤其是在清單中找不到該值的情況下
Names Default To Here(1);
test = {"a", "b", "c", "d", "e", "f"};
test2 = test || Repeat({""}, 27629);
lookup_val = "a";
repeats = 200;
tests = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests, (end-start)/1e6);
);
tests2 = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test2, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests2, (end-start)/1e6);
);
Show(Mean(tests), Std Dev(tests), Mean(tests2), Std Dev(tests2));
Show(Median(tests2)/Median(tests));
編輯:
這兩個測試腳本都寫得相當快,因此可能會出現一些錯誤
Names Default To Here(1);
Random Reset(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::10])),
New Column("second", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
Column(dt_lookup, "second") << Set Data Type("Character");
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "first"]), :first));
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "second"]), :second));
end = HP Time();
show((end - start)/1e6);
wait(0);
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "first"]) << get keys), :first));
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "second"]) << get keys), :second));
end = HP Time();
show((end - start) / 1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);
根據您有多少個值以及它們是否是字元(我認為在您的情況下它們是),使用 Summarize() 而不是 Associative Array() 來獲取唯一值會更快,但這很可能不會那麼大在這種情況下的效果
Names Default To Here(1);
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("test", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "test") << Set Data Type("Character");
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(Column(dt_lookup, "test")));
end = HP Time();
show((end - start) / 1e6);
start = HP Time();
uniq_vals2 = Associative Array(Column(dt_lookup, "test")) << get keys;
end = HP Time();
show((end - start) / 1e6);
Show(N Items(uniq_vals), N Items(uniq_vals2));
Close(dt_lookup, no save);回覆:「獲取行」的時間太長這很可能屬於過早優化的類別,但 JMP 的更新有時可能非常快,並且很可能在此處使用某些列重命名並向充滿空值的查找表添加新列
Names Default To Here(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::30000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
/*
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(:first));
r = dt_data << Get Rows Where(Contains(As Constant(uniq_vals), :first));
dt_data[r, "second"] = "";
end = HP Time();
Show((end-start)/1e6);
*/
missing_col = dt_lookup << New Column("missing_vals", Numeric, Nominal);
start = HP Time();
i = 1;
Column(dt_lookup, "first") << Set Name(Char(i));
missing_col << Set Name("second");
dt_data << Update(With(dt_lookup), Match Columns(:first = Eval(Char(i))), Replace Columns in Main Table(:second));
end = HP Time();
Show((end-start)/1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);回覆:「獲取行」的時間太長這非常有效,謝謝!
謝謝@jthi還有!沒有深入研究他在上面發布的程式碼,因為 txnelson 代碼的複製和貼上工作完美,但我很感謝他花時間製作它。