Le manque de cohérence dans la qualité des données entrave l’analyse des données et dissuade de nombreuses personnes de se lancer dans l’aventure du Machine Learning.
Dans l'industrie des semi-conducteurs, on s'attend à ce que les processus soient constamment améliorés. Malheureusement, l'un des effets secondaires de ces efforts est la modification de la structure des données. L'une des raisons pourrait être le changement de nom de l'étape du processus.
J'ai simulé un tel cas ci-dessous où 20 lots ont été traités via 4 étapes de processus avec des changements de nom d'étape.
Pour l'analyse des causes profondes, il est nécessaire de comparer les résultats des sondes provenant d'équipements associés à une étape spécifique. Dans le cas ci-dessous, nous pouvons voir que les données sont devenues stratifiées.
Je sais que je pourrais continuer à utiliser la fonctionnalité "Combiner les colonnes" dans JMP (Cols\Utilities\Combine columns...) mais en réalité j'ai plusieurs centaines de colonnes qui doivent être vérifiées et combinées.
Lorsque j'utilise la fonctionnalité Tables\Missing Data Pattern dans JMP, je peux facilement voir les structures de données et les colonnes potentielles à combiner.
Je me demandais si les informations du modèle de données manquantes pouvaient être utilisées pour écrire l'exigence de combinaison de colonnes ?
Plusieurs vérifications seraient nécessaires avant d’automatiser le processus, telles que :
Les colonnes représentent-elles la même étape du processus ?
Le contenu des deux étapes est-il similaire ?
Le modèle de données manquantes est-il inverse pour les colonnes appariées ?
Les données corrompues ressemblent à ceci :

Modèle de données manquantes :

Données reconstruites :

- jpol
Bonjour, pour ceux d'entre vous qui souhaitent utiliser le modèle de données manquantes pour améliorer la qualité des données, je donne une brève mise à jour ici :
J'avais utilisé le script par @txnelson pour créer de meilleurs ensembles de données, mais j'ai ensuite réalisé qu'il y avait un cas où je voudrais combiner des colonnes malgré que leur modèle de données manquantes respectif (et leur complément) ne corresponde pas. C'est lorsque les deux colonnes ont des données manquantes dans les mêmes lignes.
Voici un exemple, basé sur l'exemple original :

Je voudrais combiner les colonnes associées à Step6 comme vu ci-dessus.
Il m'est alors venu à l'esprit qu'il serait utile de connaître le pourcentage de correspondance entre les colonnes avant toute manipulation de données. Cela donnerait la possibilité d'utiliser ces informations pour décider de combiner ou non.
Ayant communiqué avec @txnelson il a gentiment développé son scénario.
Ci-joint la version finale.
J'inclus également ci-dessous quelques exemples utilisant des données "réelles" où cette méthode a été utilisée pour améliorer la qualité des données :
Remarque : les cellules colorées en bleu indiquent des données manquantes
Cas 1:
À partir de

pour

Cas 2 :
À partir de

pour

Il y a une grande réduction des colonnes et beaucoup moins de cellules "vides"
Comme vous pouvez l'imaginer, cela permet des analyses de cause profonde améliorées, plus rapides et plus efficaces.
Vous trouverez ci-joint les scripts pour créer l'exemple de données manquantes simulées et le script final qui rapporte "Pourcentage combinable" et "Colonnes pouvant être combinées" en fonction des modèles de données manquantes.
- Philippe
Lors de l'évaluation du script de txnelson sur une table de données beaucoup plus grande de la fabrication, il a été constaté (Jim a trouvé) que si certaines lignes n'ont pas de données dans toutes les colonnes ciblées, le script ne donnera pas de liste de sortie. Jim a gentiment fourni un correctif au script. Voir ci-dessous:
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 ) )
)
);- Philippe
Merci Jim pour la réponse et la solution très rapides.
Pour ceux qui souhaitent voir votre script en action, j'inclus le script de construction de données de l'exemple que j'ai fourni et votre JSL pour signaler les colonnes qui pourraient être combinées.
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 ) )
)
);
- Philippe
Je pense que vous pouvez utiliser le modèle de données manquantes pour identifier les colonnes qui ont des données sans intersection pour les modèles non manquants et les modèles manquants.Ce script utilise la table de sortie de la plate-forme Missing Pattern, en utilisant une table de données Missing Data Pattern légèrement modifiée à partir des tables de données JMP Sample.Il trouve tous les modèles inversement appariés, puis les affiche dans une fenêtre d'affichage

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 ) )
)
);