Objet 1
La partie difficile ici dans l'article 1 de Défi 10 n'est pas le code mais les subtilités autour de la définition du quantile. Tout d'abord, gardons les choses indépendantes de la distribution et travaillons avec l'ordre de classement des valeurs plutôt que les valeurs directement. C'est-à-dire que nous trions les valeurs par ordre croissant et les numérotons en fonction de l'endroit où elles apparaissent dans cet ordre. Nous devrons décider quoi faire avec les cravates. Nous pourrions continuer à les classer séquentiellement ou leur donner la même valeur. L'inconvénient de la première est que nous pouvons avoir la même valeur apparaissant dans plus d'un groupe. L'inconvénient de cette dernière approche est que le nombre d'articles par groupe peut être moins équilibré. Ces deux approches correspondent à la Classement et Classement Cravate Fonctions JSL. Nous n'avons pas parlé de la valeur à donner aux liens dans la deuxième approche. Nous pourrions leur donner à tous la prochaine valeur de classement séquentiel. Alternativement, nous pourrions faire la moyenne des valeurs classées séquentiellement. Dans les deux cas, nous voulons probablement donner à la prochaine valeur séquentielle non liée le rang qu'elle aurait reçu s'il n'y avait pas eu d'égalité. Classement Cravate fait la moyenne des rangs, et par souci de simplicité, nous l'utiliserons.
La question suivante est de savoir comment diviser les groupes. Nous pourrions essayer de les répartir aussi équitablement que possible. Un moyen simple de le faire serait de classer les liens de manière séquentielle en mettant au moins Sol ( N / g ) éléments dans chaque groupe (où N c'est le nombre total d'articles et g est le nombre de groupes quantiles). Nous devrons décider où mettre le N – g * Sol ( N / g ) < g valeurs supplémentaires. Le code ci-dessous s'occupe de tout cela simplement et proprement :
Plafond(Rang(inVec)/(N Row(inVec)/quant))
où enVec est le vecteur d'entrée (colonne) et quantitatif le nombre de groupes quantiles.
Le code ci-dessus peut entraîner la répartition des valeurs liées entre les groupes. Pour éviter cela, nous pouvons remplacer Classement avec Classement Cravate . Un exemple de la fonction complète est ci-dessous :
quantileGroup = Function({inVec,quant=10,method=1},{outVec,sumTblRef,ranks},
inVec = Shape(inVec,N Row(invec)*N Col(inVec),1);
If(method ==1,
outVec = Ceiling(Ranking(inVec)/(N Row(inVec)/quant)),
outVec = Ceiling(Ranking Tie(inVec)/(N Row(inVec)/quant))
);
outVec;
);
Article 2
Il existe un certain nombre de façons différentes d'agréger des groupes à faible nombre : par nombre absolu d'observations, nombre relatif d'observations (par exemple, groupes avec moins de 10 % du plus grand groupe), en fixant le nombre total de groupes, etc. a ses mérites et ses défauts. Pour apporter une solution flexible, j'ai choisi une approche à la fois interactive et visuelle, gérée avec un histogramme modulable à l'aide d'un curseur. De cette façon, je pouvais déplacer le curseur d'avant en arrière jusqu'à ce que je trouve une distribution de groupes qui semble bonne. La difficulté était de trouver un code rapide lorsque le nombre de groupes était important. Pour faire simple, je voulais travailler avec des opérations de table de données et des plates-formes (avec Recalcul automatique allumé). Voici un exemple de ce à quoi cela pourrait ressembler avant et après :
Avant

Après

D'une manière générale, ce code fonctionne en construisant un tableau récapitulatif à partir des groupes et en utilisant les comptages de groupe (le N lignes colonne) en tant que Fréq variable. Cela évite d'avoir à mettre à jour les valeurs de la table d'origine, qui peut être considérablement plus grande. Le code se trouve dans Groupes agrégés.JSL . Une liste des valeurs de groupe d'origine du résumé est stockée dans les groupes de variables globales en plus d'un ordre de classement vectoriel des nombres (classements). Déplacer le curseur exécute le agrégatLowCounts fonctions où la demande nombre de groupes ( nGroupes ) est transmis en fonction de la position du curseur. Le nombre de groupes peut être facilement sélectionné à partir du vecteur de rangs. Par exemple, si 10 groupes au total sont souhaités, la valeur de tout groupe d'origine avec un rang 10 ou supérieur est définie sur la valeur du groupe agrégé (par exemple, « Autre »), tous les autres groupes restant les mêmes. Étant donné que la table est triée, cela nécessite simplement de modifier les valeurs à partir de la ligne 10.
Article 3 / Article 4
Ma motivation pour cet article était en tant que précurseur de l'article 4. Trouver quelque chose dans un tableau associatif (AA) est beaucoup plus rapide que d'utiliser Loc . Construire un AA avec les 209 405 mots de Liste de mots.JMP a pris un peu moins de 12 secondes sur mon ordinateur. Le tableau ci-dessous montre le temps nécessaire pour trouver une liste de mots aléatoires dans le tableau en utilisant soit Loc ou un AA.
N mots
|
Loc (sec)
|
Tableau associatif (sec)
|
1
|
0,19
|
0,000045
|
5
|
0,91
|
0,000127
|
dix
|
1,78
|
0,000244
|
25
|
4.51
|
0,000592
|
50
|
9.11
|
0,001019
|
70
|
12.47
|
0,001454
|
100
|
17,82
|
0,002155
|
Pour les listes de plus de 70 mots, il vaut mieux construire l'AA. Le code que j'ai utilisé pour tester ces deux approches est en Loc contre AA.JSL .
Il y a des avantages et des inconvénients à utiliser les AA comme structures de données interrogeables. Du côté positif, vous pouvez associer n'importe quelle valeur à une clé AA, y compris d'autres AA. Les inconvénients sont que les clés doivent être uniques (ce n'est pas grave dans mon option) et, plus important encore, le processus de recherche doit être augmenté si les valeurs de recherche ne figurent pas dans la liste des clés. C'est-à-dire que la mise en œuvre est relativement facile lorsque toutes les valeurs de recherche possibles sont connues a priori, mais un peu plus délicate lorsqu'elles ne le sont pas. Cela ne veut pas dire que nous ne pouvons pas les utiliser ; nous devons juste être un peu plus rusés. Quelque chose comme le code ci-dessous fonctionnerait pour le cas mentionné dans le message tagué au point 3 . Un peu plus encombrant et probablement plus lent dans certains cas, mais extrêmement flexible. Il peut être facilement adapté aux situations où le dictionnaire de recherche change en modifiant simplement le contenu du tableau associatif.
aaMap = Associative Array(
{"1","2","3","4","5","6","7","8","9","0","M","K"},
{"1","2","3","4","5","6","7","8","9","0","e6","e3"}
);
findAndReplace = Function({inList,aaMap},
outNums = Transform Each({nextString},inList,Output("Matrix"),
nextChars = Items(nextString,"");
Num(Concat Items(Transform Each({nextChar},nextChars,aaMap[nextChar]),""));
);
outNums
);
Et si je voulais aborder quelque chose d'un peu plus général, plus gros, comme construire un dictionnaire de tous les mots qui apparaissent dans la traduction anglaise des Misérables ? Commençons par supposer qu'un mot est composé uniquement de caractères alphabétiques, y compris éventuellement des lettres en dehors du jeu de caractères ASCII standard (par exemple, ceux avec des signes diacritiques). Tout le reste est un délimiteur. Le défi ici est que nous ne savons pas quels caractères délimiteurs nous pourrions rencontrer. Puisque nous savons quels caractères composent les mots, nous pouvons supposer que s'il n'est pas dans la liste, c'est un délimiteur.
L'appariement de motifs a les outils parfaits pour trouver les mots que nous utiliserons pour construire le dictionnaire : Pat Span et Pat Pause .Nous pourrions utiliser Mots , mais alors nous devrions vérifier chaque élément pour les délimiteurs intégrés. L'utilisation de la correspondance de motifs nous permet de tout faire en une seule étape. Le code est ci-dessous. L'ensemble du processus a pris entre 8 et 9 secondes. Pour appliquer le code à un texte différent, quelques ajustements peuvent être nécessaires, tels que l'inclusion de caractères supplémentaires et l'enregistrement du fichier dans un codage différent (j'ai utilisé utf-16 pour capturer des caractères ASCII étendus). je suis redevable à @Craige_Hales pour m'avoir aidé avec cela après avoir eu du mal à le faire fonctionner. Le fichier texte des Misérables a été téléchargé à partir du Projet Gutenberg . Tu peux le trouver ici .
bigText = Load Text File("Les Misérables.txt");
aaLookup = Associative Array();
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZé´É";
wordLoc = 0;
Pat Match(bigText,
Pat Repeat(
(
Pat Pos() >> nextLoc
+ Pat Span( letters ) >> nextWord
+ Pat Test(
Try(
Insert Into(aaLookup[Lowercase(nextWord)],nextLoc),
aaLookup<<INSERT></INSERT>
Joli! Les Essayer () construction que vous utilisez pour le tableau associatif Insérer dans() peut être plus rapide que de tester d'abord un élément existant.
Quand j'étais assez jeune pour faire partie d'un cercle de lecture, un de mes copains qui a beaucoup voyagé a lu un passage avec le mot Yosémite , que je n'avais jamais rencontré. Je me souviens avoir été surpris par sa prononciation de quatre syllabes et avoir remarqué que le professeur était agréablement surpris.
Des années plus tard, quelqu'un m'a dit que je pouvais dire boiteux est rob et obtenez le nom de la pièce suffisamment correct pour échapper à l'attention.