"Obtener filas donde" está tardando demasiadoTengo una tabla de referencia donde cada columna es un nombre de una columna de la tabla de datos principal y los valores en las filas son los números de pieza que tienen datos incorrectos para esa columna en la tabla principal.Entonces, por ejemplo, en la tabla principal, la columna 1 es el número de pieza y la columna 2 es "Temp".Digamos que el número de fila es igual al número de pieza, por lo que la fila 1 es la parte "1" y digamos que tiene un valor de 65 en la columna "Temp".La parte 2 tiene una temperatura de -100 y, por lo tanto, son datos incorrectos.Entonces, en la tabla de referencia debajo de la columna denominada "Temp", el valor de la fila 1 es "2".Esto se repite para todos los números de pieza que tienen datos incorrectos en la tabla principal y luego también se repite para cada columna.
Lo que esto me proporciona es una tabla de referencia de datos incorrectos que luego puedo recorrer para eliminar automáticamente los datos incorrectos cada vez que ingreso los datos más recientes para la tabla principal.Tengo el código que funciona sin embargo la línea:
(donde vlist contiene todos los números de pieza de la tabla de referencia y dt2 es la tabla de datos principal)
try(rowindex=dt2 << Get Rows Where(contains(vlist,:WORKORDERNO )));
es súper lento.Se necesitan 22 segundos para completarse.Como tengo que revisar 196 columnas, esto lleva demasiado tiempo.¡Se agradecería cualquier sugerencia sobre cómo acelerar esto!
El código completo está aquí:
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>Automatización y secuencias de comandosventanasRe: "Obtener filas donde" tarda demasiadoConsidere cómo JMP realizará la resolución de nombres.Cuando ejecutas un Obtener filas donde() función, irá fila por fila sobre la tabla, evaluando la dónde expresión.Cada evaluación requerirá la resolución de nombres para todas las variables definidas, y dado que su lista v vairable se define fuera del ciclo en ejecución, tendrá que realizar un recorrido de alcance en cada iteración, lo que generará una gran cantidad de trabajo desperdiciado.
Para solucionar este problema, considere evaluar previamente los nombres que serán constantes durante la búsqueda, como este:
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 );Observe la Evaluación( Evaluación Expr( ... Expr(vlista) ... ) ) expresión - eso es preevaluar lista v ya que será una constante durante todo el ciclo.
Re: "Obtener filas donde" tarda demasiadoCreo que puedes usar AsConstant(vList) para lograr el mismo efecto, el nombre 'vlist' solo debe evaluarse una vez por cada llamada a GetRowsWhere.
Re: "Obtener filas donde" tarda demasiadoGracias por la respuesta @ataqueerrático , Ingresé las modificaciones de su código y el código se ejecutó en 21 segundos frente a 22 segundos.Un poco mejor, pero no donde necesito estar.¡Cualquier otra idea sería apreciada!
Re: "Obtener filas donde" tarda demasiadoTambién encuentro que usar Loc es más rápido en la mayoría de situaciones como esta, si puedes encontrar una manera de usarlo. Puede que haya una forma mejor que esta, pero puedes probar algo como esto para reemplazar la llamada 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))));
No estoy exactamente seguro de cómo están configuradas sus tablas, pero básicamente se trata de convertir los números de piezas defectuosas en una matriz asociativa donde los números de piezas defectuosas devuelven 1 y cualquier otra cosa devuelve 0. Cuando pasa una lista de todos los números de pieza a GetValues, devuelve una lista de unos y ceros para cada fila. Llamar a Loc en esto devuelve los índices donde se encuentra 1, que deben corresponder a las filas con números de piezas incorrectos.
Re: "Obtener filas donde" tarda demasiado@ataqueerrático Así que hice una tabla de datos maestros de prueba y una tabla de referencia para intentar poder compartirla para que la gente pudiera seguir el juego, pero cuando lo hice, el script se ejecutó muy rápido, en menos de un segundo.Entonces ahora me pregunto si tiene algo que ver con mi tabla de datos real.
Aquí están las tablas de prueba.

Re: "Obtener filas donde" tarda demasiadoDependiendo de sus datos, existen muchos métodos diferentes que puede utilizar para realizar estas comprobaciones (uniones/actualizaciones, ubicaciones, obtener filas dónde, matriz asociativa, tabla de resumen...). ¿Cuántas filas tienen tus tablas? ¿Cuántos valores diferentes como máximo hay en las columnas de su tabla de referencia? ¿Están la mayoría de los valores vacíos (elimine los valores vacíos antes de realizar la comparación para reducir el tamaño de la lista o inclúyalos allí solo una vez)?
Re: "Obtener filas donde" tarda demasiadoEy @jthi ,
Aquí hay una descripción general de la tabla principal:

y aquí está la tabla de referencias:

Aquí se muestra la cantidad de datos que tiene cada columna en la tabla de referencia: (de la salida del analizador de datos faltantes)
Número faltante
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
Por lo tanto, la mayoría de las columnas están llenas de "datos faltantes"/espacios en blanco debido a las pocas columnas que tienen una gran cantidad de datos incorrectos.
Me pregunto si tener todos estos espacios en blanco en la lista v está causando la desaceleración:

Re: "Obtener filas donde" tarda demasiadoSospecho que todos los espacios en blanco harán que su código se ralentice.Aquí hay una solución para eso.Simplemente reemplace su creación de vlist con
Try( vlist = Associative Array( As Column( cols[i] ) ) << get keys );
If( vlist[1] == "",
Remove From( vlist, 1, 1 )
);
Re: "Obtener filas donde" tarda demasiadoLo más probable es que cause una desaceleración, especialmente si el valor no se encuentra en la lista.
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));
Editar:
Ambos scripts de prueba se escriben con bastante rapidez, por lo que puede haber algunos errores.
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);
Dependiendo de cuántos valores tenga y si son caracteres (creo que en su caso lo son), usar Summarize() en lugar de Associative Array() para obtener los valores únicos será más rápido, pero lo más probable es que no sea tan grande. de un efecto en este 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: "Obtener filas donde" tarda demasiadoLo más probable es que esto vaya a la categoría de optimización prematura, pero la actualización de JMP a veces puede ser muy rápida y lo más probable es que se pueda usar aquí cambiando el nombre de algunas columnas y agregando una nueva columna a su tabla de búsqueda que está llena de valores vacíos.
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: "Obtener filas donde" tarda demasiado¡Esto funcionó muy bien, gracias!
Gracias a @jthi ¡también!No profundicé en el código que publicó arriba porque copiar y pegar el código de txnelson funcionó perfectamente, pero le agradezco que se haya tomado el tiempo para hacerlo.