Resalte los contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresTengo un conjunto de distribuciones que contienen una población de unidades. He utilizado un select where con una llamada containsitem para seleccionar los elementos de la lista en mi conjunto de datos que coinciden con números de identificación de referencia de DUT específicos. Esto ayuda a mostrar qué contenedores contienen las mediciones para las unidades de interés. Me gustaría utilizar la fecha de prueba para cada instancia de la selección para resaltar el contenedor que contiene las mediciones. Por ejemplo, si la misma unidad se probó el 20/6/2024 y luego se probó nuevamente el 25/6/2024, luego una vez más el 28/6/2024. El resultado del contenedor del 20/6 se resaltaría con un color y el resultado del contenedor del 25/6, 28/6 tendría otros dos colores. Algunos otros objetivos son que estos colores sean consistentes en todas las distribuciones del informe (un color para cada fecha de prueba), y que todas las unidades no seleccionadas permanezcan con el color predeterminado. También me gustaría que el resaltado sea de arriba a abajo del gráfico para el contenedor respectivo.
Su apoyo es muy apreciado.
//dtmain << select where(:SN=="12346777" | :SN=="12346982");
dtmain << select where(ContainsItem(:SN, {"12346777", "12346982"}));
Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :Average ),
Horizontal Layout( 1 ),
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
),
Continuous Distribution(
Column( :Min ),
Horizontal Layout( 1 ),
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
),
Continuous Distribution(
Column( :Max ),
Horizontal Layout( 1 ),
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
),
By(
:TID, :BLOCKNAME, :MEAS_TYPE
)
);

Maqueta de lo que me gustaría lograr:

Análisis y modelado de datos básicosAnálisis de confiabilidadRe: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedores¿Podrías elegir un archivo adecuado de la carpeta de muestras y crear una maqueta que ilustre el problema?
Los beneficios:
- ahorra tiempo (#1) :
Ningún usuario necesita crear un conjunto de datos de maqueta - ahorra tiempo (#2):
Ayuda a comprender el problema - Todas las respuestas se basarán en una maqueta común.
-> fácil de comparar

Por ejemplo, con datos de temperatura, selección de estado y colores por trimestre (en lugar de los datos originales, selección de DUT y colores por fechas de medición): ¿es esto lo que le interesa?
Este vídeo se está procesando actualmente. Inténtalo de nuevo en unos minutos.
(ver en Mis Videos)
dt = Open( "$SAMPLE_DATA/Functional Data/Weekly Weather Data.jmp" );
dt << New Column( "selected Quarter",
"Ordinal",
Formula( If( Selected(), Quarter( :DATE ) ) ),
Set Property(
"Value Colors",
{1 = -13912408, 2 = -4042310, 3 = -4354269, 4 = -13400361}
)
);
dt << Graph Builder(
Transform Column( "temperature", Formula( Round( :TAVG / 2 ) * 2 ) ),
Size( 568, 328 ),
Show Control Panel( 0 ),
Variables( X( :STATION ), X( :temperature ), Overlay( :selected Quarter ) ),
Elements( Position( 1, 1 ), Bar( X, Overlay( 0 ), Legend( 9 ), Bar Style( "Stacked" ) ) ),
Elements( Position( 2, 1 ), Bar( X, Legend( 1 ), Bar Style( "Stacked" ) ) ),
SendToReport(
Dispatch( {}, "400", ScaleBox,
{Legend Model( 1, Properties( 0, {Fill Color( 32 )}, Item ID( "Missing", 1 ) ) )}
),
Dispatch( {}, "Graph Builder", FrameBox( 2 ), {Fill Selection Mode( "Unselected Faded" )} )
)
);
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresQuizás puedas hacer esto con líneas de referencia.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
dist = dt << Distribution(
Stack(1),
Continuous Distribution(
Column(:height),
Horizontal Layout(1),
Vertical(0),
Set Bin Width(2),
Process Capability(0)
)
);
ab = Report(dist)[AxisBox(1)];
ab << Add Ref Line({60, 62}, "Solid", "Red", "", 1, 0.25);
ab << Add Ref Line({62, 64}, "Solid", "Green", "", 1, 0.25);
ab << Add Ref Line({64, 66}, "Solid", "Blue", "", 1, 0.25);

o utilizando scripts gráficos
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
dist = dt << Distribution(
Stack(1),
Continuous Distribution(
Column(:height),
Horizontal Layout(1),
Vertical(0),
Set Bin Width(2),
Process Capability(0)
)
);
fb = Report(dist)[FrameBox(2)];
fb << Add Graphics Script(
1,
Transparency(0.2);
Fill Color("Red");
Rect(68, Y Range() + 10, 70, Y Origin(), 1);
Transparency(0.2);
Fill Color("Light Green");
Rect(70, Y Range() + 10, 72, Y Origin(), 1);
);

Para obtener la misma coloración en todas las distribuciones, puede establecer la propiedad de colores para sus fechas y utilizarla al configurar los colores, o crear una lista de colores y usarlos en orden.
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresEsta es mi versión de cómo hacerlo. Busca las filas seleccionadas y los contenedores asociados a ellas y luego agrega las líneas de referencia según sea necesario.

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
// For illustration, randomly select some rows
For( i = 1, i <= 3, i++,
dt << select rows( Random Integer( 1, N Rows( dt ) ) )
);
dist = dt << Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :height ),
Quantiles( 0 ),
Summary Statistics( 0 ),
Horizontal Layout( 1 ),
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
)
);
distRPT = Report( dist )[AxisBox( 1 )];
// Find the Midpoints of the bins the selected rows are in
dist << Save( "Level Midpoints" );
theBins = (Associative Array( Column( dt, N Cols( dt ) )[dt << get selected rows] )) << get keys;
dt << delete columns( N Cols( dt ) );
// Get the Increment of the X axis
theIncr = distRPT[AxisBox( 1 )] << get inc;
// Add the reference lines for each selected bin
For Each( {bin, index}, theBins,
binList = {};
Insert Into( binList, bin - theIncr / 2 );
Insert Into( binList, bin + theIncr / 2 );
Eval( Eval Expr( distRPT << Add Ref Line( Expr( binList ), "Solid", Expr( Index + 2 ), "", 1, 0.25 ) ) );
);
Una expansión de esto para que el gráfico cambie de forma interactiva a medida que el usuario selecciona y deselecciona diferentes filas requeriría agregar un controlador RowState y algo de lógica que primero eliminaría todas las líneas de referencia existentes y luego agregaría las nuevas.
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresUna pregunta para responder:
¿Cómo se deben asignar los colores y cómo se debe marcar el rango?
por ejemplo si los datos 6/20 para los ID seleccionados son: 48, 90 (77, 56, ...).
O a la inversa: ¿podemos estar seguros de que los datos de todos los ID de dispositivos seleccionados en una fecha están en el mismo contenedor?
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresTomado nota. Gracias. Adaptaré mi pregunta para utilizar los datos disponibles como me sugeriste.
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresGracias por el apoyo.
Pude usar la función Add Ref como tú y @jthi sugirieron. Usé el enfoque para la coloración y confirmé que funcionará para una sola distribución. Cuando agrego condiciones By, pierdo la capacidad de direccionamiento de la gráfica, lo que genera errores.
Como sugirió @hogi, cambié a los datos disponibles para esta pregunta. Para facilitar la respuesta, amplié Big Class con una versión modificada del guión de Jim. Estos son los pasos que seguí y los resultados
1. Importar clase grande
2. Agregue algunos datos condicionalmente si la columna "Estado" no está en la tabla
a. Agregue una columna denominada Estado con datos secuenciados para ubicar a las personas en "CA", "WA" u "OR".
b. Agregue una segunda "PATTY" que tiene 16 años, "F", 57, 134 y está en "WA".
3. Selecciona algunos nombres. Elegí LESLIE y PATTY
4. Ejecute el script para buscar y resaltar los contenedores de interés.
DE ACUERDO Case - remove By (:State) from the script below and change the preceding comma to a semicolon to run successfully. The code finds both instances of Patty and uses different colors for each of them. If they had the same height, for this example the reference lines would overlap only showing one of the two colors.
@hogi planteó un buen punto sobre el arbitraje del color que se muestra. Una vez que comprenda el direccionamiento de los elementos, planeo agregar una condición para el caso en que aparezca más de un punto de datos interesante en el mismo contenedor.

Caso NG : ejecuto una distribución con una condición By basada en :State y veo un error al direccionar el objeto de gráfico. Probé algunas permutaciones de direccionamiento sin éxito. Me falta información clave para acceder a AxisBox.
Tampoco funcionó:
distRPT = Report( dist )["altura",AxisBox( 1 )];
distRPT = Report( dist )["Estado=WA",altura",AxisBox( 1 )];
distRPT = Informe( dist["Estado=WA"] )["altura",AxisBox( 1 )];
Código de error de ejemplo: objeto no suscribible en la fila 41 en el acceso o evaluación de 'Report(dist)[ /*###*/AxisBox(1)]' , Report( dist )[/*###*/AxisBox( 1 )]
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
col_name_list = dt << get column names(string);
newColName = "State";
// New column: State
if (!contains(col_name_list, newColName),
Local( {dt, tempStrings},
dt = Data Table( "Big Class" );
dt << New Column( "State", Character, "Nominal" ) << Begin Data Update;
tempStrings = {"CA", "WA", "OR"};
For Each Row( dt, :State = tempStrings[Sequence( 1, 3, 1, 1 )] );
dt << End Data Update;
);
//Make it a double Patty :), another person with the same name.
dt << Add Rows( 1, At End );
//Cheat and use a constant of 41 for the last row index
dt[[41],{name,age,sex,height,weight,State}] = {{"PATTY", 16, "F", 57, 134, "WA"}};
);
// For illustration, select some names
dt << select where( ContainsItem(:name, {"LESLIE","PATTY"}));
dist = dt << Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :height ),
Quantiles( 0 ),
Summary Statistics( 0 ),
Horizontal Layout( 1 ),
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
),
By (:State)
);
distRPT = Report( dist )[AxisBox( 1 )];
// Find the Midpoints of the bins the selected rows are in
dist << Save( "Level Midpoints" );
theBins = (Associative Array( Column( dt, N Cols( dt ) )[dt << get selected rows] )) << get keys;
dt << delete columns( N Cols( dt ) );
// Get the Increment of the X axis
theIncr = distRPT[AxisBox( 1 )] << get inc;
// Add the reference lines for each selected bin
For Each( {bin, index}, theBins,
binList = {};
Insert Into( binList, bin - theIncr / 2 );
Insert Into( binList, bin + theIncr / 2 );
Eval( Eval Expr( distRPT << Add Ref Line( Expr( binList ), "Solid", Expr( Index + 2 ), "", 1, 0.25 ) ) );
);
Sus comentarios y orientación son apreciados.
¡Gracias!
Bryan
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoreslindo : )
En cuanto a "encontrar el cuadro del eje correcto", este deseo en la Lista de deseos:
Facilitar la obtención de resultados de los informes mediante JSL
tiene el estado "en la cola" - Espero que, además de "facilitar la obtención de resultados de los informes", también facilite la forma de encontrar el cuadro del eje correcto...
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresMi primera suposición es que estás intentando usar la función Report() en una lista (verifica qué contiene dist usando Show(dist);) cuando estás usando By
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresSi necesitas los grupos BY, la cosa se vuelve un poco más complicada.
Cada subparcela puede tener distintos anchos de bin. Por eso es necesario un bucle for:
- para obtener los anchos de los contenedores individuales.
- para obtener las filas seleccionadas para la subparcela específica
- para agregar las líneas de referencia a la subtrama específica.
Hm, tal vez repensar la idea de las regiones sombreadas: también tenemos el problema con los colores.
Por el momento, simplemente aplicamos un color diferente a cada contenedor seleccionado . Las regiones sombreadas se ven bien, pero el ancho es bastante arbitrario. ¿Quizás simplemente agregue una línea por cada ID seleccionado? ¿Cuántos "ID" desea seleccionar?
Cuando huele a cinta adhesiva, es hora de preguntar: ¿estamos reinventando la rueda?
En general, Graph Builder puede hacer estas cosas automáticamente sin necesidad de hablar con la capa del informe...
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
col_name_list = dt << get column names( string );
newColName = "State";
// New column: State
If( !Contains( col_name_list, newColName ),
Local( {dt, tempStrings},
dt = Data Table( "Big Class" );
dt << New Column( "State", Character, "Nominal" ) << Begin Data Update;
tempStrings = {"CA", "WA", "OR"};
For Each Row( dt, :State = tempStrings[Sequence( 1, 3, 1, 1 )] );
dt << End Data Update;
);
//Make it a double Patty :), another person with the same name.
dt << Add Rows( 1, At End );
//Cheat and use a constant of 41 for the last row index
dt[[41], {name, age, sex, height, weight, State}] = {{"PATTY", 16, "F", 57, 134, "WA"}};
);
// For illustration, select some names
dt << select where( Contains Item( :name, {"LESLIE", "PATTY"} ) );
dist = dt << Distribution(
Stack( 1 ),
Continuous Distribution(
Column( :height ),
Quantiles( 0 ),
Summary Statistics( 0 ),
Horizontal Layout( 1 ),
Normal Quantile Plot( 0 ), // disable, if the user enabled it in the preferences :)
Vertical( 0 ),
Set Bin Width( 2 ),
Process Capability( 0 )
),
By( :State )
);
// get all reports
// if there is a BY group, get the info - if there is none, put it into a list
If( Is List( dist ),
dists=dist;
myBys = Transform each ({myexpr} , dist << Get Where Expr, Arg(myExpr , 2 ))
, //no By
dists = Eval List( {dist} );
myBys= {};
);
//get the reports
distRPTs = Transform Each( {dist}, dists, Report( dist ) );
// Find the Midpoints of the bins the selected rows are in
dist << Save( "Level Midpoints" );
//loop though the By groups and add the reflines
For Each( {report, idx}, distRPTs,
//report = distRPTs[2]; idx=2;
selected rows = dt << get selected rows;
// there is a BY group -> restrict the selection
if(N Items(myBys),
Eval( Eval Expr( selected rows = dt << get rows where( Contains( Expr( selected rows ), Row() ) & :State == Expr( myBys[idx] ) ) ) );
);
theBins = (Associative Array( Column( dt, N Cols( dt ) )[selected rows] )) << get keys;
// Get the Increment of the X axis
theIncr = report[AxisBox( 1 )] << get inc;
// Add the reference lines for each selected bin
For Each( {bin, index}, theBins,
//bin = 57; index=1
binList = {};
Insert Into( binList, bin - theIncr / 2 );
Insert Into( binList, bin + theIncr / 2 );
Eval( Eval Expr(report[AxisBox( 1 )] << Add Ref Line( Expr( binList ), "Solid", Expr( Index + 2 ), "", 1, 0.25 ) ) );
);
);
dt << delete columns( N Cols( dt ) );Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresa través de Graph Builder:
Este vídeo se está procesando actualmente. Inténtalo de nuevo en unos minutos.
(ver en Mis Videos)
New Column( "selected",
Character,
Formula( If( Col Maximum( Selected( Row State() ), :name ), :name, "-" ) )
)
New Window( "try",
H List Box(
Graph Builder( Size( 519, 452 ), Show Control Panel( 0 ), Show Legend( 0 ), Variables( X( :name ) ), Elements( Bar( X ) ) );
gb = Graph Builder(
Size( 487, 500 ),
Show Control Panel( 0 ),
Variables( X( :height ), Wrap( :State ), Color( :selected ) ),
Elements(
Heatmap( X, Legend( 8 ) ),
Histogram( X, Legend( 6 ), Response Scale( "Fill" ) ),
Points( X, Legend( 9 ), Jitter( "None" ) )
),
SendToReport(
Dispatch( {}, "400", ScaleBox,
{Legend Model( 8, Properties( 0, {Transparency( 0 )}, Item ID( "-", 1 ) ) ), Legend Model(
9,
Properties( 0, {Transparency( 0 )}, Item ID( "-", 1 ) )
)}
)
)
);
)
);
(gb << xpath( "//FrameBox" )) << {Marker Drawing Mode( "Outlined" ), Marker Size( 10 ), Transparency( 0.5 ),
Fill Selection Mode( "Unselected Faded" )};
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresGracias por sus respuestas. Pude adaptar el código para abordar las parcelas individuales. En mi análisis, tengo tres subparcelas para cada conjunto de condiciones. Recurrí a codificar el índice de subparcelas.
If( Is List( rptDist ),
dists=rptDist;
myBys1 = Transform each ({myexpr} , rptDist << Get Where Expr, Arg(myExpr , 1 ));
myBys2 = Transform each ({myexpr} , rptDist << Get Where Expr, Arg(myExpr , 2 ));
myBys3 = Transform each ({myexpr} , rptDist << Get Where Expr, Arg(myExpr , 3 ));
, //else condition - no By conditions in Distribution call
dists = Eval List( {rptDist} );
myBys= {};
);A por un nuevo desafío, en el que el uso de llamadas de matriz asociativa hace perder información. Crearé una publicación aparte para el próximo desafío, ya que se logró el objetivo de trazado aquí.
¡Gracias a todos!
Re: Resaltar contenedores en una distribución en función de un valor de columna para resaltar la migración de contenedoresHola jarmo,
I've added the nested for loops which achieved the desired result. Without the second loop the added reference would only appear in the first of the three plots. Please note that I assigned numOfPlots a constant value of 3. I was looking for a way to interrogate the report(AxisBox... for dimensions, but I did not find the right object to return the correct count.
En total, hay tres bucles for anidados para producir distribuciones y anotarlas con líneas de referencia.
...
For Each( {report, idx}, distRPTs, //grab each report in the
...
For Each( {bin, index}, theBins, //process bin for each report
...
For( iPlot = 1, iPlot <= numOfPlots, iPlot +=1, << add refer. in each of the subplots.
...
...<BR />For Each( {bin, index}, theBins,
binList = {};
//TBD change bin width to avoid offset when bin width is an odd number
Insert Into( binList, bin - theIncr / 2 );
Insert Into( binList, bin + theIncr / 2 );
For( iPlot = 1, iPlot <= numOfPlots, iPlot +=1,
Eval( Eval Expr(report[AxisBox( iPlot )] << Add Ref Line( Expr( binList ), "Solid", Expr( Index + 2 ), "", 1, 0.25 ) ) );
);
);