Gegenstand 1
Der herausfordernde Teil hier in Punkt 1 von Herausforderung 10 ist nicht der Code, sondern die Feinheiten rund um die Definition von Quantil. Lassen Sie uns zunächst die Verteilung unabhängig halten und mit der Rangfolge der Werte arbeiten und nicht direkt mit den Werten. Das heißt, wir sortieren die Werte in aufsteigender Reihenfolge und nummerieren sie entsprechend ihrer Position in dieser Reihenfolge. Wir müssen entscheiden, was wir mit Bindungen machen. Wir könnten sie der Reihe nach weiter ordnen oder ihnen den gleichen Wert zuweisen. Der Nachteil der ersteren besteht darin, dass derselbe Wert in mehr als einer Gruppe auftritt. Der Nachteil des letzteren Ansatzes besteht darin, dass die Anzahl der Elemente pro Gruppe möglicherweise weniger ausgewogen ist. Diese beiden Ansätze entsprechen dem Rangfolge und Ranglisten-Unentschieden JSL-Funktionen. Wir haben nicht darüber gesprochen, welchen Wert wir den Verbindungen im zweiten Ansatz geben sollen. Wir könnten ihnen allen den nächstfolgenden Rangfolgewert geben. Alternativ könnten wir die sequentiell geordneten Werte mitteln. In beiden Fällen möchten wir wahrscheinlich dem nächsten sequentiellen, nicht gebundenen Wert den Rang geben, den er ohne Gleichstand erhalten hätte. Ranglisten-Unentschieden mittelt die Ränge, und der Einfachheit halber werden wir dies verwenden.
Die nächste Frage ist, wie man die Gruppen aufteilt. Wir könnten versuchen, sie so gleichmäßig wie möglich aufzuteilen. Eine einfache Möglichkeit, dies zu tun, besteht darin, die Krawatten nacheinander zu ordnen, mindestens Boden ( n / g ) Elemente in jeder Gruppe (wobei n es die Gesamtzahl der Artikel und g ist die Anzahl der Quantilgruppen). Wir müssen uns entscheiden, wo wir das hinstellen n – g * Boden ( n / g ) < g zusätzliche Werte. Der folgende Code kümmert sich um all dies einfach und sauber:
Obergrenze(Ranking(inVec)/(N Row(inVec)/quant))
wo inVec ist der Eingabe-(Spalten-)Vektor und Quant die Anzahl der Quantilgruppen.
Der obige Code kann dazu führen, dass gebundene Werte auf Gruppen aufgeteilt werden. Um dies zu vermeiden, können wir ersetzen Rangfolge mit Ranglisten-Unentschieden . Ein Beispiel für die vollständige Funktion ist unten:
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;
);
Artikel 2
Es gibt verschiedene Möglichkeiten, Gruppen mit niedriger Anzahl zusammenzufassen: nach absoluter Anzahl von Beobachtungen, relativer Anzahl von Beobachtungen (z. B. Gruppen mit einer Anzahl von weniger als 10 % der größten Gruppe), Festlegen der Gesamtanzahl von Gruppen usw. Jeder hat seine Vorzüge und Mängel. Um eine flexible Lösung zu bieten, habe ich mich für einen interaktiven und visuellen Ansatz entschieden, der mit einem Balkendiagramm verwaltet wird, das mithilfe eines Schiebereglers angepasst werden kann. Auf diese Weise konnte ich den Schieberegler hin und her bewegen, bis ich eine Gruppenverteilung gefunden hatte, die gut aussah. Die Schwierigkeit bestand darin, einen schnellen Code zu entwickeln, wenn die Anzahl der Gruppen groß war. Der Einfachheit halber wollte ich mit Datentabellenoperationen und Plattformen arbeiten (mit Automatische Neuberechnung eingeschaltet). Nachfolgend sehen Sie ein Beispiel, wie dies vorher und nachher aussehen könnte:
Vor

Nach

Im Allgemeinen funktioniert dieser Code, indem er eine Übersichtstabelle aus den Gruppen erstellt und die Gruppenzahlen verwendet (die N Reihen Spalte) als a Freq Variable. Dadurch entfällt die Notwendigkeit, Werte aus der Originaltabelle zu aktualisieren, die erheblich größer sein kann. Den Code finden Sie in Gruppen aggregieren.JSL . Eine Liste der ursprünglichen Gruppenwerte aus der Zusammenfassung wird in den globalen Variablengruppen zusätzlich zu einer Vektor-Rangfolge der Zählungen (Ränge) gespeichert. Durch Verschieben des Schiebereglers wird der aggregierenLowCounts Funktionen, bei denen die Anforderungsanzahl der Gruppen ( nGruppen ) wird basierend auf der Position des Schiebereglers übergeben. Die Anzahl der Gruppen kann leicht aus dem Rangvektor ausgewählt werden. Wenn beispielsweise insgesamt 10 Gruppen gewünscht werden, wird der Wert für alle ursprünglichen Gruppen mit einem Rang von 10 oder höher auf den aggregierten Gruppenwert (z. B. „Sonstige“) gesetzt, wobei alle anderen Gruppen gleich bleiben. Da die Tabelle sortiert ist, müssen dazu lediglich Werte ab Zeile 10 geändert werden.
Artikel 3 / Artikel 4
Meine Motivation für diesen Artikel war als Vorläufer von Artikel 4. Etwas in einem assoziativen Array (AA) zu finden ist Welten schneller als das Verwenden Lok . Erstellen einer AA mit den 209.405 Wörtern aus Wortliste.JMP dauerte auf meinem Computer etwas weniger als 12 Sekunden. Die folgende Tabelle zeigt die Zeit, um eine Liste zufälliger Wörter aus der Tabelle zu finden, indem Sie entweder Lok oder ein AA.
N Wörter
|
Lok (Sek.)
|
Assoziatives Array (Sek.)
|
1
|
0,19
|
0.000045
|
5
|
0,91
|
0,000127
|
10
|
1,78
|
0,000244
|
25
|
4,51
|
0,000592
|
50
|
9.11
|
0,001019
|
70
|
12.47
|
0,001454
|
100
|
17.82
|
0,002155
|
Bei Listen mit mehr als 70 Wörtern lohnt es sich, die AA zu erstellen. Der Code, den ich zum Testen dieser beiden Ansätze verwendet habe, ist in Loc vs AA.JSL .
Die Verwendung von AAs als durchsuchbare Datenstrukturen hat Vor- und Nachteile. Auf der positiven Seite können Sie einem AA-Schlüssel jeden beliebigen Wert zuordnen, einschließlich anderer AAs. Die Nachteile sind, dass Schlüssel eindeutig sein müssen (bei meiner Option keine große Sache) und, was noch wichtiger ist, der Suchprozess erweitert werden muss, wenn Suchwerte nicht in der Liste der Schlüssel enthalten sind. Das heißt, die Implementierung ist relativ einfach, wenn alle möglichen Suchwerte a priori bekannt sind, aber etwas schwieriger, wenn sie es nicht sind. Dies bedeutet nicht, dass wir sie nicht verwenden können; wir müssen nur ein bisschen schlauer sein. Etwas wie der folgende Code würde funktionieren für der Fall, der in dem Beitrag erwähnt wird, der in Punkt 3 markiert ist . Etwas umständlicher und in manchen Fällen wahrscheinlich langsamer, aber extrem flexibel. Es kann leicht an Situationen angepasst werden, in denen sich das Nachschlagewörterbuch ändert, indem einfach der Inhalt des assoziativen Arrays geändert wird.
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
);
Was wäre, wenn ich etwas Allgemeineres, Größeres angehen wollte, wie zum Beispiel ein Wörterbuch mit allen Wörtern zu erstellen, die in der englischen Übersetzung von Les Misérables vorkommen? Beginnen wir mit der Annahme, dass ein Wort nur aus alphabetischen Zeichen besteht, einschließlich möglicherweise Buchstaben außerhalb des Standard-ASCII-Zeichensatzes (zB solche mit diakritischen Zeichen). Alles andere ist ein Trennzeichen. Die Herausforderung dabei ist, dass wir uns nicht sicher sind, auf welche abgrenzenden Zeichen wir stoßen könnten. Da wir wissen, aus welchen Zeichen Wörter bestehen, können wir davon ausgehen, dass es sich um ein Trennzeichen handelt, wenn es nicht in der Liste enthalten ist.
Der Mustervergleich bietet die perfekten Werkzeuge, um die Wörter zu finden, die wir zum Erstellen des Wörterbuchs verwenden: Pat Span und Pat Break .Wir könnten es gebrauchen Wörter , aber dann müssten wir jedes Element auf eingebettete Trennzeichen überprüfen. Mit dem Mustervergleich können wir alles in einem Schritt erledigen. Der Code ist unten. Der gesamte Vorgang dauerte zwischen 8 und 9 Sekunden. Um den Code auf einen anderen Text anzuwenden, kann eine Feinabstimmung erforderlich sein, z. B. das Einfügen zusätzlicher Zeichen und das Speichern der Datei in einer anderen Kodierung (ich habe utf-16 verwendet, um erweiterte ASCII-Zeichen zu erfassen). Ich bin zu Dank verpflichtet @Craige_Hales dafür, dass Sie mir dabei geholfen haben, nachdem ich mich bemüht hatte, es zum Laufen zu bringen. Die Textdatei zu Les Misérables wurde von der Projekt Gutenberg . Du kannst es finden Hier .
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>
Schön! Die Versuchen () Konstrukt, das Sie für das assoziative Array verwenden Einfügen in() kann schneller sein, als zuerst auf ein vorhandenes Element zu testen.
Als ich jung genug war, um in einem Lesekreis zu sein, durfte einer meiner weitgereisten Kumpels eine Passage mit dem Wort lesen Yosemite , was mir noch nie begegnet war. Ich erinnere mich, dass ich von seiner viersilbigen Aussprache überrascht war und bemerkte, dass der Lehrer angenehm überrascht war.
Jahre später sagte mir jemand, dass ich sagen könnte Lahm ist Rob und erhalten Sie den Namen des Stücks richtig genug, um der Aufmerksamkeit zu entgehen.