"Ottieni righe dove" sta impiegando troppo tempoHo una tabella di riferimento in cui ogni colonna è un nome di una colonna della tabella dati principale e i valori nelle righe sono i numeri di parte che contengono dati errati per quella colonna nella tabella principale.Quindi, ad esempio, nella tabella principale la colonna 1 è il codice articolo e la colonna 2 è "Temp".Diciamo che il numero di riga è uguale al numero di parte, quindi la riga 1 è la parte "1" e diciamo che ha un valore di 65 nella colonna "Temp".La parte 2 ha una temperatura di -100 e quindi i dati non sono validi.Pertanto nella tabella di riferimento sotto la colonna denominata "Temp" il valore della riga 1 è "2".Ciò viene ripetuto per tutti i codici articolo che contengono dati errati nella tabella principale e quindi viene ripetuto anche per ciascuna colonna.
Ciò che mi dà è una tabella di riferimento di dati errati che posso quindi scorrere per rimuovere automaticamente i dati errati ogni volta che inserisco i dati più recenti per la tabella principale.Ho il codice che funziona comunque la riga:
(dove vlist contiene tutti i codici della tabella di riferimento e dt2 è la tabella dati principale)
try(rowindex=dt2 << Get Rows Where(contains(vlist,:WORKORDERNO )));
è super lento.Ci vogliono 22 secondi per completarlo.Dato che ho 196 colonne da esaminare, questo richiede molto tempo.Eventuali suggerimenti su come accelerare il processo sarebbero apprezzati!
Il codice completo è qui:
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>Automazione e scriptingfinestreRe: "Ottieni righe dove" sta impiegando troppo tempoConsidera come JMP eseguirà la risoluzione dei nomi.Quando esegui a Ottieni righe dove() funzione, andrà riga per riga sulla tabella, valutando il file Dove espressione.Ogni valutazione richiederà la risoluzione dei nomi per tutte le variabili definite e poiché your vlist vairable è definito al di fuori del ciclo di esecuzione, dovrà eseguire alcune passeggiate nell'ambito di ogni iterazione, portando a molto lavoro sprecato.
Per aggirare questo problema, prendi in considerazione la possibilità di pre-valutare tutti i nomi che saranno costanti durante tutta la ricerca, in questo modo:
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 );Notare il Eval( Eval Espr( ... Espr( vlist ) ... )) espressione: questa è una pre-valutazione vlist poiché sarà una costante per tutto il ciclo.
Re: "Ottieni righe dove" sta impiegando troppo tempoCredo che tu possa usare AsConstant(vList) per ottenere lo stesso effetto, il nome "vlist" dovrebbe essere valutato solo una volta per ogni chiamata GetRowsWhere.
Re: "Ottieni righe dove" sta impiegando troppo tempoGrazie per la risposta @ErraticAttack , ho inserito le modifiche al codice e il codice è stato eseguito in 21 secondi contro 22 secondi.Quindi un po' meglio, ma non dove dovrei essere.Qualsiasi altra idea sarà apprezzata!
Re: "Ottieni righe dove" sta impiegando troppo tempoTrovo anche che usare Loc sia più veloce nella maggior parte delle situazioni come questa, se riesci a trovare un modo per usarlo. Potrebbe esserci un modo migliore di questo, ma puoi provare qualcosa di simile per sostituire la chiamata 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))));
Non sono esattamente sicuro di come siano impostate le tue tabelle, ma fondamentalmente sta trasformando i numeri di parte errati in un array associativo in cui i numeri di parte errati restituiscono 1 e qualsiasi altra cosa restituisce 0. Quando passi un elenco di tutti i numeri di parte a GetValues, restituisce un elenco di 1 e 0 per ogni riga. Chiamando Loc su questo vengono restituiti gli indici in cui si trova 1, che dovrebbe corrispondere alle righe con numeri di parte errati.
Re: "Ottieni righe dove" sta impiegando troppo tempo@ErraticAttack Quindi ho creato una tabella di dati principali di prova e una tabella di riferimento per cercare di poterla condividere in modo che le persone potessero giocare, ma quando l'ho fatto lo script funziona molto velocemente, meno di un secondo.Quindi ora mi chiedo se ha qualcosa a che fare con la mia tabella dati effettiva?
Ecco le tabelle di prova

Re: "Ottieni righe dove" sta impiegando troppo tempoA seconda dei dati, esistono molti metodi diversi che è possibile utilizzare per eseguire questi controlli (join/aggiornamenti, loc, ottieni righe dove, array associativo, tabella di riepilogo...). Quante righe hanno le tue tabelle? Quanti valori diversi al massimo nelle colonne della tabella di riferimento? La maggior parte dei valori sono vuoti (rimuovi i valori vuoti prima di eseguire il confronto per ridurre l'elenco o includerlo solo una volta)?
Re: "Ottieni righe dove" sta impiegando troppo tempoEHI @jthi ,
Ecco una panoramica della tabella principale:

ed ecco la tabella di riferimento:

Ecco quanti dati contiene ciascuna colonna nella tabella di riferimento: (dall'output dello screener dati mancanti)
Numero mancante
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
Quindi la maggior parte delle colonne sono piene di "dati mancanti"/spazi vuoti a causa delle poche colonne che contengono moltissimi dati errati.
Mi chiedo se avere tutti questi spazi vuoti nella vlist stia causando il rallentamento:

Re: "Ottieni righe dove" sta impiegando troppo tempoSospetto che tutti gli spazi vuoti rallenteranno il tuo codice.Ecco una soluzione per questo.Basta sostituire la creazione della vlist con
Try( vlist = Associative Array( As Column( cols[i] ) ) << get keys );
If( vlist[1] == "",
Remove From( vlist, 1, 1 )
);
Re: "Ottieni righe dove" sta impiegando troppo tempoMolto probabilmente causerà un rallentamento, soprattutto se il valore non viene trovato dall'elenco
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));
Modificare:
Entrambi questi script di test vengono scritti abbastanza rapidamente, quindi potrebbero esserci degli errori
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);
A seconda di quanti valori hai e se sono caratteri (penso che nel tuo caso lo siano), usare Summarize() invece di Associative Array() per ottenere i valori univoci sarà più veloce ma molto probabilmente non sarà così grande di un effetto in questo caso
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);Re: "Ottieni righe dove" sta impiegando troppo tempoQuesto rientra molto probabilmente nella categoria dell'ottimizzazione prematura, ma l'aggiornamento di JMP a volte può essere molto veloce e molto probabilmente potrebbe essere utilizzato qui con la ridenominazione di alcune colonne e l'aggiunta di nuove colonne alla tabella di ricerca che è piena di valori vuoti
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);Re: "Ottieni righe dove" sta impiegando troppo tempoHa funzionato benissimo, grazie!
Grazie a @jthi anche!Non ho approfondito il codice che ha pubblicato sopra poiché il copia e incolla del codice txnelson ha funzionato perfettamente, ma apprezzo che si sia preso il tempo per realizzarlo.