La falta de una calidad consistente de los datos dificulta el análisis de datos y disuade a muchos de embarcarse en un viaje de aprendizaje automático.
En la industria de semiconductores se espera que los procesos mejoren continuamente. Lamentablemente, uno de los efectos secundarios de estos esfuerzos es el cambio en la estructura de los datos. Una razón para ello podría ser el cambio de nombre de los pasos del proceso.
A continuación he simulado un caso en el que se han procesado 20 lotes a través de 4 pasos de proceso con cambios de nombre de paso.
Para el análisis de causa raíz es necesario comparar los resultados de las pruebas de los equipos asociados a un paso específico. En el caso que se muestra a continuación, podemos ver que los datos se han estratificado.
Sé que podría seguir usando la función "Combinar columnas" en JMP (Cols\Utilities\Combinar columnas...) pero en realidad tengo varios cientos de columnas que necesitan ser revisadas y combinadas.
Al utilizar la función Tablas\Patrón de datos faltantes en JMP, puedo ver fácilmente las estructuras de datos y las columnas potenciales que se combinarán.
Me preguntaba si la información del Patrón de datos faltantes podría usarse para crear un script para el requisito de combinar columnas.
Serían necesarias varias comprobaciones antes de automatizar el proceso, como por ejemplo:
¿Las columnas representan el mismo paso en el proceso?
¿El contenido de ambos pasos es similar?
¿El patrón de datos faltantes es inverso para columnas emparejadas?
Los datos dañados se ven así:

Patrón de datos faltantes:

Datos reconstruidos:

- JPOL
Hola, para aquellos de ustedes interesados en usar el patrón de datos faltantes para mejorar la calidad de los datos, les doy una breve actualización aquí:
Yo había estado usando el guión por @txnelson para crear mejores conjuntos de datos, pero luego me di cuenta de que hay una instancia en la que me gustaría combinar columnas a pesar de que sus respectivos patrones de datos faltantes (y complemento) no coinciden. Es cuando a ambas columnas les faltan datos en las mismas filas.
Aquí hay un ejemplo, basado en el ejemplo original:

Me gustaría combinar columnas asociadas con Step6 como se ve arriba.
Entonces se me ocurrió que sería útil conocer el porcentaje de coincidencia entre columnas antes de cualquier manejo de datos. Esto daría la posibilidad de utilizar dicha información al decidir si combinar o no.
Habiéndose comunicado con @txnelson amablemente desarrolló su guión.
Se adjunta la versión final.
También incluyo a continuación algunos ejemplos que utilizan datos "reales" en los que este método se ha utilizado para mejorar la calidad de los datos:
Nota: las celdas de color azul indican datos faltantes
Caso 1:
De

a

Caso 2:
De

a

Hay una gran reducción en las columnas y muchas menos celdas "vacías".
Como puede imaginar, esto permite análisis de causa raíz mejorados, más rápidos y más eficientes.
Se adjuntan las secuencias de comandos para hacer el ejemplo de datos faltantes simulados y la secuencia de comandos final que informa "Porcentaje combinable" y "Columnas que se pueden combinar" según los patrones de datos faltantes.
- Felipe
Al evaluar la secuencia de comandos de txnelson en una tabla de datos mucho más grande de fabricación, se encontró (encontró Jim) que si ciertas filas no tienen datos en todas las columnas específicas, la secuencia de comandos no proporcionará una lista de salida. Jim ha proporcionado amablemente una solución al guión. Vea abajo:
Names Default To Here( 1 );
dtRaw = Current Data Table();
colNamesList = dtRaw << get column names( string );
Remove From( colNamesList, 1, 1 );
dt = dtRaw << Missing Data Pattern(
columns( Eval( colNamesList ) ),
Output Table( "Missing Data Pattern" )
);
// Get rid of all missing and all present patterns
dt << lock data table( 0 );
dt << select where( Contains( :patterns, "0" ) & !Contains( :Patterns, "1" ) );
Try( dt << delete rows );
dt << select where( Contains( :patterns, "1" ) & !Contains( :Patterns, "0" ) );
Try( dt << delete rows );
// Check for columns which could be combined
// *** JSL written by txnelson ***
cols1List = {};
cols2List = {};
For( i = 4, i <= N Cols( dt ), i++,
comp = Associative Array( dt << get rows where( As Column( dt, i ) == 1 ) );
compMissing = Associative Array( dt << get rows where( As Column( dt, i ) == 0 ) );
If( N Items( comp ) > 0,
For( k = i + 1, k <= N Cols( dt ), k++,
comp2 = Associative Array( dt << get rows where( As Column( dt, k ) == 1 ) );
comp2Missing = Associative Array( dt << get rows where( As Column( dt, k ) == 0 ) );
comp2 << intersect( comp );
comp2Missing << intersect( compMissing );
If( N Items( comp2 << get keys ) == 0 & N Items( comp2Missing << get keys ) == 0,
Insert Into( cols1List, Column( dt, i ) << get name );
Insert Into( cols2List, Column( dt, k ) << get name );
);
)
);
);
nw = New Window( "Results",
Outline Box( "Columns that can be combined",
Table Box( String Col Box( "Column", cols1List ), String Col Box( "With", cols2List ) )
)
);- Felipe
Gracias Jim por la rápida respuesta y solución.
Para aquellos que deseen ver su secuencia de comandos en acción, incluyo la secuencia de comandos de creación de datos del ejemplo que proporcioné y su JSL para informar las columnas que podrían combinarse.
names default to here(1);
// Construct the initial data table
New Table( "Missing data initial",
Add Rows( 20 ),
New Column( "LOT_ID",
Character,
"Nominal",
Set Values(
{"AA_234_xx.1", "AA_234_xx.2", "AA_234_xx.3", "AA_234_xx.4",
"AA_234_xx.5", "AA_234_xx.6", "AA_234_xx.7", "AA_234_xx.8",
"AA_234_xx.9", "AA_234_xx.10", "AA_234_xx.11", "AA_234_xx.12",
"AA_234_xx.13", "AA_234_xx.14", "AA_234_xx.15", "AA_234_xx.16",
"AA_234_xx.17", "AA_234_xx.18", "AA_234_xx.19", "AA_234_xx.20"}
),
Set Display Width( 81 )
),
New Column( "Step1.v1",
Character( 6 ),
"Nominal",
Set Values(
{"SRD_01", "SRD_02", "SRD_01", "SRD_04", "SRD_02", "", "", "", "", "",
"SRD_01", "SRD_02", "SRD_01", "SRD_04", "SRD_02", "", "", "", "", ""}
),
Set Display Width( 58 )
),
New Column( "Step1.v2",
Character( 16 ),
"Nominal",
Set Values(
{"", "", "", "", "", "SRD_01", "SRD_02", "SRD_01", "SRD_04", "SRD_02",
"", "", "", "", "", "SRD_02", "SRD_02", "SRD_02", "SRD_02", "SRD_02"}
),
Set Display Width( 58 )
),
New Column( "Step2.v2",
Character( 16 ),
"Nominal",
Set Values(
{"COATER_02", "COATER_01", "", "", "COATER_02", "COATER_01", "COATER_02",
"COATER_02", "COATER_02", "COATER_01", "COATER_02", "COATER_02",
"COATER_01", "COATER_01", "COATER_01", "", "", "", "COATER_01",
"COATER_01"}
),
Set Display Width( 71 )
),
New Column( "Step2.v3",
Character( 16 ),
"Nominal",
Set Values(
{"", "", "COATER_01", "COATER_01", "", "", "", "", "", "", "", "", "",
"", "", "COATER_02", "COATER_02", "COATER_02", "", ""}
),
Set Display Width( 71 )
),
New Column( "Step3.v5",
Character( 16 ),
"Nominal",
Set Values(
{"DRIE_03", "DRIE_04", "DRIE_03", "", "", "", "", "", "", "DRIE_04",
"DRIE_03", "DRIE_04", "DRIE_03", "DRIE_04", "", "", "", "", "", ""}
),
Set Display Width( 58 )
),
New Column( "Step3.v6",
Character( 16 ),
"Nominal",
Set Values(
{"", "", "", "DRIE_04", "DRIE_03", "DRIE_04", "DRIE_03", "DRIE_04",
"DRIE_03", "", "", "", "", "", "DRIE_03", "DRIE_04", "DRIE_03",
"DRIE_04", "DRIE_03", "DRIE_04"}
),
Set Display Width( 58 )
),
New Column( "Step4.v1",
Character( 16 ),
"Nominal",
Set Values(
{"PRIME_06", "", "PRIME_07", "", "PRIME_06", "", "PRIME_07", "",
"PRIME_06", "", "PRIME_07", "", "PRIME_06", "", "PRIME_07", "",
"PRIME_06", "", "PRIME_07", ""}
),
Set Display Width( 61 )
),
New Column( "Step4.v2",
Character( 16 ),
"Nominal",
Set Values(
{"", "PRIME_06", "", "PRIME_07", "", "PRIME_06", "", "PRIME_07", "",
"PRIME_06", "", "PRIME_07", "", "PRIME_06", "", "PRIME_07", "",
"PRIME_06", "", "PRIME_07"}
),
Set Display Width( 61 )
)
);
// Check the Missings Data Patern
Data Table( "Missing data initial" ) <<
Missing Data Pattern(
columns(
:Step1.v1,
:Step1.v2,
:Step2.v2,
:Step2.v3,
:Step3.v5,
:Step3.v6,
:Step4.v1,
:Step4.v2
),
Output Table( "Missing Data Pattern" )
);
// Check for columns which could be combined
// *** JSL written by txnelson ***
dt=Data Table( "Missing Data Pattern");
cols1List = {};
cols2List = {};
For( i = 4, i <= N Cols( dt ), i++,
comp = Associative Array( dt << get rows where( As Column( dt, i ) == 1 ) );
compMissing = Associative Array( dt << get rows where( As Column( dt, i ) == 0 ) );
If( N Items( comp ) > 0,
For( k = i + 1, k <= N Cols( dt ), k++,
comp2 = Associative Array( dt << get rows where( As Column( dt, k ) == 1 ) );
comp2Missing = Associative Array( dt << get rows where( As Column( dt, k ) == 0 ) );
comp2 << intersect( comp );
comp2Missing << intersect( compMissing );
If( N Items( comp2 << get keys ) == 0 & N Items( comp2Missing << get keys ) == 0,
Insert Into( cols1List, Column( dt, i ) << get name );
Insert Into( cols2List, Column( dt, k ) << get name );
);
)
);
);
nw = New Window( "Results",
Outline Box( "Columns that can be combined",
Table Box( String Col Box( "Column", cols1List ), String Col Box( "With", cols2List ) )
)
);
- Felipe
Creo que puede usar el patrón de datos faltantes para identificar las columnas que tienen datos sin intersección para los patrones que no faltan y los patrones que faltan.Este script usa la tabla de salida de la plataforma Missing Pattern, usando una tabla de datos Missing Data Pattern ligeramente modificada de las tablas de datos de JMP Sample.Encuentra todos los patrones inversamente coincidentes y luego los muestra en una ventana de visualización

names default to here(1);
dt=New Table( "example",
Add Rows( 4 ),
New Column( "Count",
Numeric,
"Continuous",
Format( "Fixed Dec", 10, 0 ),
Preselect Role( Freq ),
Set Values( [1, 3, 1, 2] )
),
New Column( "Number of columns missing",
Numeric,
"Continuous",
Format( "Fixed Dec", 10, 0 ),
Set Values( [1, 2, 1, 2] )
),
New Column( "Patterns",
Character,
"Ordinal",
List Check( {"0010", "0011", "0100", "0101"} ),
Set Values( {"0010", "0011", "0100", "0101"} )
),
New Column( "Trial 1", Numeric( 1 ), "Nominal", Set Values( [0, 0, 0, 0] ) ),
New Column( "Trial 2", Numeric( 1 ), "Nominal", Set Values( [0, 0, 1, 1] ) ),
New Column( "Trial 3", Numeric( 1 ), "Nominal", Set Values( [1, 1, 0, 0] ) ),
New Column( "Trial 4", Numeric( 1 ), "Nominal", Set Values( [0, 1, 0, 1] ) )
);
cols1List = {};
cols2List = {};
For( i = 4, i <= N Cols( dt ), i++,
comp = Associative Array( dt << get rows where( As Column( dt, i ) == 1 ) );
compMissing = Associative Array( dt << get rows where( As Column( dt, i ) == 0 ) );
If( N Items( comp ) > 0,
For( k = i + 1, k <= N Cols( dt ), k++,
comp2 = Associative Array( dt << get rows where( As Column( dt, k ) == 1 ) );
comp2Missing = Associative Array( dt << get rows where( As Column( dt, k ) == 0 ) );
comp2 << intersect( comp );
comp2Missing << intersect( compMissing );
If( N Items( comp2 << get keys ) == 0 & N Items( comp2Missing << get keys ) == 0,
Insert Into( cols1List, Column( dt, i ) << get name );
Insert Into( cols2List, Column( dt, k ) << get name );
);
)
);
);
nw = New Window( "Results",
Outline Box( "Columns that can be combined",
Table Box( String Col Box( "Column", cols1List ), String Col Box( "With", cols2List ) )
)
);