"Obtenir des lignes là où" prend beaucoup de tempsJ'ai une table de référence dans laquelle chaque colonne est un nom d'une colonne de la table de données principale et les valeurs dans les lignes sont les numéros de pièce qui contiennent des données incorrectes pour cette colonne dans la table principale.Ainsi, par exemple, dans le tableau principal, la colonne 1 est le numéro de pièce et la colonne 2 est « Temp ».Disons que le numéro de ligne est égal au numéro de pièce, donc la ligne 1 est la partie "1" et disons qu'elle a une valeur de 65 dans la colonne "Temp".La partie 2 a une température de -100 et contient donc de mauvaises données.Ainsi, dans le tableau de référence sous la colonne nommée « Temp », la valeur de la ligne 1 est « 2 ».Ceci est répété pour tous les numéros de pièces qui contiennent des données incorrectes dans la table principale, puis également pour chaque colonne.
Cela me donne une mauvaise table de référence de données que je peux ensuite parcourir pour supprimer automatiquement les mauvaises données chaque fois que j'extrait les données les plus récentes pour la table principale.J'ai le code qui fonctionne cependant la ligne :
(où vlist contient tous les numéros de pièces de la table de référence et dt2 est la table de données principale)
try(rowindex=dt2 << Get Rows Where(contains(vlist,:WORKORDERNO )));
est super lent.Cela prend 22 secondes pour que cela soit terminé.Comme j'ai 196 colonnes à parcourir, cela prend beaucoup trop de temps.Toutes les suggestions sur la façon d’accélérer cela seraient appréciées !
Le code complet est ici :
names default to here(1);
dt=open("J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp", invisible(1)); //this is the reference table
dt<<BEGIN data="https://community.jmp.com/" update=""></BEGIN>Automatisation et scriptsles fenêtresRe: "Obtenir les lignes où" prend beaucoup trop de tempsConsidérez comment JMP effectuera la résolution de noms.Lorsque vous exécutez un Obtenir les lignes où() fonction, il parcourra ligne par ligne le tableau, évaluant le où expression.Chaque évaluation nécessitera une résolution de nom pour toutes les variables définies, et puisque votre liste virtuelle variable est défini en dehors de la boucle d'exécution, il devra parcourir la portée à chaque itération, ce qui entraînera beaucoup de travail inutile.
Pour contourner ce problème, envisagez de pré-évaluer tous les noms qui seront constants tout au long de la recherche, comme ceci :
Names Default To Here( 1 );
dt = Open(
"J:\Public\Ti Process Control\Dashboard Files\JMP data for CC's\Limits\master_data_table_clean_up.jmp",
invisible( 1 )
); //this is the reference table
dt << begin data update;
cols = dt << get column names();
dt2 = Data Table( "Master data pull daily download" ); //this is the main table
dt2 << begin data update;
dt2 << Clear Select();
cols2 = dt2 << get column names();
vlist = {};
For( i = 1, i <= 2 /*N items(cols)*/, i++,
Try( vlist = Column( dt, cols[i] ) << get values );
starttime = Tick Seconds();
Eval( Eval Expr(
Try( rowindex = dt2 << Get Rows Where( Contains( Expr( vlist ), :WORKORDERNO ) ) );
) );
endtime = Tick Seconds();
Print( "run time", Eval Insert( "Analysis took ^round(endtime - starttime)^ seconds" ) );
Try( Column( dt2, cols[i] )[rowindex] = . );
);
dt2 << end data update;
dt << end data update;
Close( dt, nosave );Remarquez le Eval( Eval Expr( ... Expr( vlist ) ... ) ) expression - c'est-à-dire une pré-évaluation liste virtuelle puisque ce sera une constante tout au long de la boucle.
Re: "Obtenir les lignes où" prend beaucoup trop de tempsJe pense que vous pouvez utiliser AsConstant(vList) pour obtenir le même effet, le nom « vlist » ne doit être évalué qu'une seule fois pour chaque appel GetRowsWhere.
Re: "Obtenir les lignes où" prend beaucoup trop de tempsMerci pour la réponse @ErraticAttack , j'ai inséré vos modifications de code et le code exécuté en 21 secondes contre 22 secondes.Donc un peu mieux mais pas là où je dois être.Toute autre idée serait appréciée !
Re: "Obtenir les lignes où" prend beaucoup trop de tempsJe trouve également que l'utilisation de Loc est plus rapide dans la plupart des situations comme celle-ci, si vous pouvez trouver un moyen de l'utiliser. Il existe peut-être un meilleur moyen que celui-ci, mais vous pouvez essayer quelque chose comme celui-ci pour remplacer l'appel GetRowsWhere.
dt = New Table( "BadTable",
Add Rows( 100 ),
New Column( "BadPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
dt2 = New Table( "FullTable",
Add Rows( 10000 ),
New Column( "NewPartNumbers",
Formula( Random Integer( 1000 ) ),
),
);
newPNumbers = dt2:NewPartNumbers<< GetValues;
badPNumbers = AssociativeArray(dt:BadPartNumbers << GetValues);
rowIndex = Loc(Matrix(badPNumbers << GetValues(AsList(newPNumbers))));
Je ne sais pas exactement comment vos tables sont configurées, mais en gros, cela transforme les numéros de pièces défectueux en un tableau associatif où les numéros de pièces défectueux renvoient 1 et tout le reste renvoie 0. Lorsque vous transmettez une liste de tous les numéros de pièces à GetValues, il renvoie une liste de 1 et de 0 pour chaque ligne. L'appel de Loc renvoie les indices où 1 se trouve, qui doivent correspondre aux lignes avec des numéros de pièces incorrects.
Re: "Obtenir les lignes où" prend beaucoup trop de temps@ErraticAttack J'ai donc créé une table de données principales de test et une table de référence pour essayer de pouvoir les partager afin que les gens puissent jouer le jeu, mais lorsque je l'ai fait, le script s'exécute très rapidement, en moins d'une seconde.Alors maintenant, je me demande si cela a quelque chose à voir avec ma table de données réelle ?
Voici les tableaux de test

Re: "Obtenir les lignes où" prend beaucoup trop de tempsEn fonction de vos données, il existe de nombreuses méthodes différentes que vous pouvez utiliser pour effectuer ces vérifications (jointures/mises à jour, loc, obtenir les lignes où, tableau associatif, tableau récapitulatif...). Combien de lignes ont vos tableaux ? Combien de valeurs différentes au maximum dans les colonnes de votre table de référence ? La plupart des valeurs sont-elles vides (supprimez les valeurs vides avant d'effectuer une comparaison pour réduire la liste ou l'inclure une seule fois) ?
Re: "Obtenir les lignes où" prend beaucoup trop de tempsHé @jthi ,
Voici un aperçu du tableau principal :

et voici le tableau des références :

Voici la quantité de données contenue dans chaque colonne de la table de référence : (à partir de la sortie du filtre de données manquantes)
Numéro manquant
0
0
0
0
3115
6075
12237
16591
16591
16591
16591
16772
17038
17093
17095
17095
17099
17099
17109
17110
17113
21542
22781
23634
24792
24792
25058
25172
25280
25341
25356
25376
25376
25827
25863
25875
25893
25894
25897
25905
25942
25957
25963
25963
25963
25965
25968
25968
25968
25968
26367
26564
27190
27404
27414
27420
27437
27453
27465
27474
27478
27493
27503
27522
27547
27553
27573
27592
27597
27597
27597
27597
27619
27626
27628
27628
27629
27629
27629
27629
Ainsi, la plupart des colonnes sont pleines de « données manquantes »/vides en raison des quelques colonnes qui contiennent une tonne de mauvaises données.
Je me demande si le fait d'avoir tous ces blancs dans la vlist provoque le ralentissement :

Re: "Obtenir les lignes où" prend beaucoup trop de tempsJe soupçonne que tous les espaces ralentiront votre code.Voici une solution pour cela.Remplacez simplement votre création de la vlist par
Try( vlist = Associative Array( As Column( cols[i] ) ) << get keys );
If( vlist[1] == "",
Remove From( vlist, 1, 1 )
);
Re: "Obtenir les lignes où" prend beaucoup trop de tempsCela entraînera très probablement un ralentissement, surtout si la valeur n'est pas trouvée dans la liste.
Names Default To Here(1);
test = {"a", "b", "c", "d", "e", "f"};
test2 = test || Repeat({""}, 27629);
lookup_val = "a";
repeats = 200;
tests = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests, (end-start)/1e6);
);
tests2 = {};
For(i = 1, i <= repeats, i++,
start = HP Time();
Contains(test2, lookup_val);
wait(0);
end = HP Time();
Insert Into(tests2, (end-start)/1e6);
);
Show(Mean(tests), Std Dev(tests), Mean(tests2), Std Dev(tests2));
Show(Median(tests2)/Median(tests));
Modifier:
Ces deux scripts de test sont écrits assez rapidement, il peut donc y avoir des erreurs.
Names Default To Here(1);
Random Reset(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::10])),
New Column("second", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
Column(dt_lookup, "second") << Set Data Type("Character");
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "first"]), :first));
dt_data << Get Rows Where(Contains(As Constant(dt_lookup[0, "second"]), :second));
end = HP Time();
show((end - start)/1e6);
wait(0);
start = HP Time();
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "first"]) << get keys), :first));
dt_data << Get Rows Where(Contains(As Constant(Associative Array(dt_lookup[0, "second"]) << get keys), :second));
end = HP Time();
show((end - start) / 1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);
En fonction du nombre de valeurs que vous avez et s'il s'agit de caractères (je pense que dans votre cas, ce sont les cas), utiliser Summarize() au lieu d'Associative Array() pour obtenir les valeurs uniques sera plus rapide, mais cela n'aura probablement pas une telle valeur. d'un effet dans ce cas
Names Default To Here(1);
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("test", Numeric, Nominal, Values(Random Shuffle(1::1000)[1::500])),
invisible
);
Column(dt_lookup, "test") << Set Data Type("Character");
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(Column(dt_lookup, "test")));
end = HP Time();
show((end - start) / 1e6);
start = HP Time();
uniq_vals2 = Associative Array(Column(dt_lookup, "test")) << get keys;
end = HP Time();
show((end - start) / 1e6);
Show(N Items(uniq_vals), N Items(uniq_vals2));
Close(dt_lookup, no save);Re: "Obtenir les lignes où" prend beaucoup trop de tempsCela relève très probablement de la catégorie d'optimisation prématurée, mais la mise à jour de JMP peut parfois être très rapide et elle pourrait très probablement être utilisée ici avec un renommage de colonnes et l'ajout d'une nouvelle colonne à votre table de recherche qui est pleine de valeurs vides.
Names Default To Here(1);
dt_data = New Table("Data",
Add Rows(30000),
New Column("first", Numeric, Nominal, << Set Each Value(Row())),
New Column("second", Numeric, Nominal, << Set Each Value(Row())),
invisible
);
Column(dt_data, "first") << Set Data Type("Character");
Column(dt_data, "second") << Set Data Type("Character");
dt_lookup = New Table("Lookup",
Add Rows(5000),
New Column("first", Numeric, Nominal, Values(Random Shuffle(1::30000)[1::500])),
invisible
);
Column(dt_lookup, "first") << Set Data Type("Character");
/*
start = HP Time();
Summarize(dt_lookup, uniq_vals = by(:first));
r = dt_data << Get Rows Where(Contains(As Constant(uniq_vals), :first));
dt_data[r, "second"] = "";
end = HP Time();
Show((end-start)/1e6);
*/
missing_col = dt_lookup << New Column("missing_vals", Numeric, Nominal);
start = HP Time();
i = 1;
Column(dt_lookup, "first") << Set Name(Char(i));
missing_col << Set Name("second");
dt_data << Update(With(dt_lookup), Match Columns(:first = Eval(Char(i))), Replace Columns in Main Table(:second));
end = HP Time();
Show((end-start)/1e6);
Close(dt_data, no save);
Close(dt_lookup, no save);Re: "Obtenir les lignes où" prend beaucoup trop de tempsCela a très bien fonctionné, merci !
Grâce à @jthi aussi!Je n'ai pas fouillé son code qu'il a publié ci-dessus car le copier-coller du code txnelson a parfaitement fonctionné, mais j'apprécie qu'il ait pris le temps de le créer.