¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?El script al final de esta publicación básicamente hace lo que quiero que haga (es decir, encontrar columnas donde un valor Y es 100 para tiempo = 0), pero también genera un mensaje de registro que me incomoda un poco (habiendo pisado en trampas antes):
A message with an empty Boolean argument enabled an option that was already enabled. That option remains enabled. In previous versions of JMP, this would have disabled the option.
Este mensaje se imprime en el registro para cada columna que se selecciona nuevamente, después de que ya se haya seleccionado una vez como parte de la construcción de mi ciclo. Como alguien relativamente nuevo en la creación de scripts, tengo dos preocupaciones principales:
- ¿Este mensaje de registro es algo que debo evitar por completo y tendré problemas? Eventualmente procesaré tablas más grandes, por lo que este mensaje de registro puede imprimirse cientos de veces para la ejecución de un solo script.
- ¿Existe una forma más inteligente de encontrar todas las columnas de una tabla que tengan un valor Y = 100 para cada fila donde el tiempo = 0? (En mi caso, estaré procesando tablas con muchas columnas, algunas de las cuales contienen resultados que están normalizados al 100% rel. en el tiempo =0. Estas son las columnas que me interesan).
Names Default To Here( 1 );
// table required for example
dt = New Table( "Results (absolute & relative) vs time",
Add Rows( 8 ),
New Column( "time",
Numeric,
Set Values( [0, 1, 2, 3, 0, 1, 2, 3] ),
),
New Column( "Y1_absolute",
Numeric,
Set Values( [7, 8, 1, 9, 0.2, 0.4, 0.65, 0.98] ),
),
New Column( "Y1-relative",
Numeric,
Set Values( [100, 114, 14, 129, 100, 200, 325, 490] ),
),
New Column( "Y2_absolute",
Numeric,
Set Values( [12, 6, 4, 0, 80, 90, 120, 75] ),
),
New Column( "Y2_relative",
Numeric,
Set Values( [100, 50, 33, 0, 100, 113, 150, 94] ),
)
);
// selecting columns where for :time == 0 a Y-value == 100 is found
For( i = 1, i <= N Row( dt ), i++,
For( j = 1, j <= N Col( dt ), j++,
If( Column( j )[i] == 0,
For( k = 1, k <= N Col( dt ), k++,
If( Column( k )[i] == 100,
Column( k ) << Set Selected
)
)
)
)
);
Tabla de datossecuencias de comandosRe: ¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?FWIW, esto evita la tabla de subconjuntos, pero probablemente no sea mucho más rápido:
Names Default To Here( 1 );
// table required for example
dt = New Table( "Results (absolute & relative) vs time",
Add Rows( 8 ),
New Column( "time",
Numeric,
Set Values( [0, 1, 2, 3, 0, 1, 2, 3] ),
),
New Column( "Y1_absolute",
Numeric,
Set Values( [7, 8, 1, 9, 0.2, 0.4, 0.65, 0.98] ),
),
New Column( "Y1-relative",
Numeric,
Set Values( [100, 114, 14, 129, 100, 200, 325, 490] ),
),
New Column( "Y2_absolute",
Numeric,
Set Values( [12, 6, 4, 0, 80, 90, 120, 75] ),
),
New Column( "Y2_relative",
Numeric,
Set Values( [100, 50, 33, 0, 100, 113, 150, 94] ),
)
);
// Rows that have time = 0
r0 = dt << getRowsWhere(:time == 0);
// Loop over other columns (assumes time is in the first column)
for(c=2, c<=NCol(dt), c++,
if(Contains(Column(dt, c)[r0], 100), Column(dt, c) << setSelected(1));
);
Re: ¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?Gracias de nuevo. La creación de subconjuntos mejoró el rendimiento en mi tabla real (grande). Solución mejorada publicada a continuación. Había pensado en esto antes, pero obviamente necesitaba un breve descanso para llegar allí. Sin embargo, lo que ni siquiera había considerado era crear una lista de columnas y eliminar elementos de forma iterativa. ¡Gracias también por eso!
Names Default To Here( 1 );
// new table required for example
dt = New Table( "Results (absolute & relative) vs time",
Add Rows( 8 ),
New Column( "time",
Numeric,
Set Values( [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] ),
),
New Column( "Y1_absolute",
Numeric,
Set Values( [7, 8, 1, 9, 0.2, 0.4, 0.65, 0.98, 0.7, ., 0.83, 0.4] ),
),
New Column( "Y1-relative",
Numeric,
Set Values( [100, 114, 14, 129, ., 200, 325, 490, 100, 330, 540, 213] ),
),
New Column( "Y2_absolute",
Numeric,
Set Values( [12, 6, 4, 0, 80, 90, 120, 75, 8.3, 9.7, 6.4, 5.2] ),
),
New Column( "Y2_relative",
Numeric,
Set Values( [., 50, 33, 0, 100, 113, 150, 94, 100, 66, 37, 12] ),
)
);
// finding and selecting Y columns where for any :time == 0 a value of 100 is found in the same row
dt << Select Where( dt:time == 0 );
dtTemp = dt << Subset ( Selected Rows, Selected Columns Only( 0 ) );
For( i = 1, i <= N Row( dtTemp ), i++,
For( j = 1, j <= N Col( dtTemp ), j++,
If( Column( dtTemp, j )[i] == 100,
Column( dt, j ) << Set Selected( 1 ),
)
)
);
Close( dtTemp, no save );
dt << Clear Select( );
Re: ¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?Algunas ideas:
Podrías probar y dividir la tabla en time=0 antes de continuar con tu bucle. Eso descomprimiría una capa de su bucle for.
Puede crear una lista de columnas y eliminar las que haya seleccionado. Luego, para cada iteración siguiente, solo tendría que recorrer las columnas restantes no seleccionadas.
Re: ¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?¡Muy apreciado! Creo que editaré ese bucle un poco más.
- No hay motivo para recorrer toda la tabla una vez que se han identificado las columnas correctas. (Editar: eso podría ser un poco difícil de hacer con mi nivel de habilidad actual. Diferentes columnas Y pueden tener valores faltantes en diferentes filas. Necesito encontrar todas las columnas Y donde el tiempo = 0 coincida con uno o más valores Y = 100).
- ¿Por qué recorrer todas las filas y no solo aquellas en las que el tiempo es realmente cero?
Editar: Me quedé con la solución presentada. Parece robusto y no quería usar aún más tiempo. Pero la viñeta #2, es decir, no recorrer todas las filas de la tabla es algo que debería y probablemente analizaré en algún momento.
Re: ¿Mejor manera de seleccionar columnas que coincidan con los criterios en otra columna en la misma tabla?Agregar (1) después de << conjunto seleccionado soluciona el mensaje de error. En lugar de alternarlo, está definiendo el estado final que desea:
For( i = 1, i <= N Row( dt ), i++,
For( j = 1, j <= N Col( dt ), j++,
If( Column( j )[i] == 0,
For( k = 1, k <= N Col( dt ), k++,
If( Column( k )[i] == 100,
Column( k ) << Set Selected(1)
)
)
)
)
);