Parece una pregunta fácil de resolver, pero estoy un poco atascado.
Tengo un conjunto de datos con 250 filas y aproximadamente 20K columnas. Las filas se dividen en dos categorías: buenas (249 filas) y malas (1 fila). Necesito encontrar todas las columnas en las que la fila 'MALO' tiene el valor más alto / más bajo que el resto de las filas 'BUENAS'.
¿Puedes sugerir alguna forma eficiente de hacer esto?
¡Gracias!
Así es como lo haría, suponiendo que tenga una columna que identifique la 1 fila incorrecta y todas las 249 filas correctas.
1) Apile todas sus 20k filas, manteniendo la columna que identifica la fila Bad y todas las filas Good
Tablas ==> Pila
2) Resumir la tabla apilada resultante
a. Agrupar por la nueva columna "Etiqueta"
si. Subgrupo por la columna que identifica los datos Malo y Bueno
C. Especifique para calcular el Min y Max para la columna "Datos"
3) En la tabla de resumen resultante
a. Agregue una nueva columna llamada "Min Max" usando la fórmula
If(
:Name( "Max(Data,Bad)" ) > :Name( "Max(Data,Good)" ), "Max",
:Name( "Min(Data,Bad)" ) < :Name( "Min(Data,Good)" ), "Min",
"Neither"
)
A continuación se muestra un script de ejemplo que creará los resultados anteriores. Utiliza una tabla de datos de ejemplo con solo 4 columnas, sin embargo, funcionará para su tabla de 20k cambiando el nombre en el script que apunta a la columna con las filas Bad y Good (llamada "GoodBad" en la tabla de datos de ejemplo), al nombre de la columna en su tabla de datos que identifica los datos incorrectos y buenos.
El script también asume que todas las columnas numéricas deben ser comparadas.
Names Default To Here( 1 );
// Create a simple data table for illustration
dt = New Table( "simple",
Add Rows( 10 ),
New Column( "A", Set Values( [59, 61, 55, 66, 52, 60, 61, 51, 60, 61] ) ),
New Column( "B",
Format( "Fixed Dec", 5, 0 ),
Set Values( [22, 123, 74, 145, 64, 84, 128, 79, 112, 107] )
),
New Column( "C",
Set Values( [110, 96, 100, 92, 92, 97, 98, 94, 91, 94] ),
),
New Column( "GoodBad",
Character,
Set Values(
{"Bad", "Good", "Good", "Good", "Good", "Good", "Good", "Good", "Good", "Good"}
)
)
);
// Get All Numeric Columns
numericCols = dt << get column names(numeric);
// Stack all of the numeric
dtStack = dt << Stack(invisible,
columns( numericCols ),
Source Label Column( "Label" ),
Stacked Data Column( "Data" )
);
// Summarize the data
dtSum = dtStack << Summary(
Group( :Label ),
Min( :Data ),
Max( :Data ),
Subgroup( :GoodBad ),
Freq( "None" ),
Weight( "None" ),
Link to original data table( 0 )
);<BR /><BR />// Delete the no longer needed Stacked data table<BR />
<SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #008000; font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: pre; word-spacing: 0px;">close( dtStack, nosave );</SPAN><BR />// Add the column that determines if Bad column is < or > Good
dtSum << New Column(
"Max or Min",
formula(
If(
:Name( "Max(Data,Bad)" ) > :Name( "Max(Data,Good)" ), "Max",
:Name( "Min(Data,Bad)" ) < :Name( "Min(Data,Good)" ), "Min",
"Neither"
)
)
);
@D_T_M ,
@txnelson , Jim, le proporcionó una solución buena y fácil de seguir que se puede hacer con la interfaz JMP y las funciones de columna. A continuación se muestra una solución alternativa usando JSL y matrices.
No estoy seguro de qué enfoque tendría el mejor rendimiento. Si no está familiarizado con la notación de matriz JMP, ni JSL, considere esta respuesta solo como un FYI para otros en la comunidad JMP.
Names Default To Here( 1 );
// Create a simple data table for illustration
dt = New Table( "simple",
Add Rows( 10 ),
New Column( "A", Set Values( [59, 66, 55, 66, 52, 60, 61, 51, 60, 61] ) ),
New Column( "B",
Format( "Fixed Dec", 5, 0 ),
Set Values( [123, 22, 74, 145, 64, 84, 128, 79, 112, 107] )
),
New Column( "C",
Set Values( [96, 110, 100, 92, 92, 97, 98, 94, 91, 94] ),
)
);
cnames = dt << get column names("string"); //need to remove column names that are not to be tested<BR />//typically cnames = cnames[n::n+249999]
//Matrix of bad row - assuming you know which row is bad, row 2.
bmat = dt[2,1::3];
glist = Remove( AsList(1::nrow(dt))[1], 2);
gmax = V Max(dt[ glist, 1::3 ]); //returns a row vector of each column max
gmin = V Min(dt[ glist, 1::3 ]); //returns a row vector of each column min
mxcol = loc(bmat - gmax > 0); //returns a row vector of column # where bmat > gmax
mncol = Loc(bmat - gmin < 0); //returns a row vector of column # where bmat < gmin
HiCol = cnames[transpose(mxcol)];
LoCol = cnames[transpose(mncol)];
show(HiCol, LoCol);
/*:
HiCol = {"C"};
LoCol = {"B"};