Gegenstand 1
Der herausfordernde Teil hier in Punkt 1 von Herausforderung 10 ist nicht der Code, sondern die Feinheiten rund um die Definition des Quantils. Lassen Sie uns zunächst die Verteilungsunabhängigkeit gewährleisten und mit der Rangfolge der Werte und nicht mit den Werten direkt arbeiten. Das heißt, wir sortieren Werte in aufsteigender Reihenfolge und nummerieren sie entsprechend ihrer Position in dieser Reihenfolge. Wir müssen entscheiden, was mit Krawatten geschehen soll. Wir könnten sie weiterhin der Reihe nach einordnen oder ihnen den gleichen Wert geben. Der Nachteil des ersteren besteht darin, dass derselbe Wert möglicherweise in mehr als einer Gruppe auftritt. Der Nachteil des letztgenannten Ansatzes besteht darin, dass die Anzahl der Elemente pro Gruppe möglicherweise weniger ausgeglichen ist. Diese beiden Ansätze entsprechen dem Rangfolge Und Ranglistengleichstand JSL-Funktionen. Wir haben nicht darüber gesprochen, welchen Wert wir den Bindungen im zweiten Ansatz beimessen sollen. Wir könnten ihnen allen den nächstfolgenden Rangfolgewert geben. Alternativ könnten wir die sequenziell geordneten Werte mitteln. In beiden Fällen möchten wir wahrscheinlich dem nächsten sequenziellen, nicht gebundenen Wert den Rang zuweisen, den er erhalten hätte, wenn es keine Bindungen gäbe. Ranglistengleichstand 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, wäre, die Unentschieden nacheinander zu ordnen Boden ( N / G ) Elemente in jeder Gruppe (wobei N Es ist die Gesamtzahl der Artikel und G ist die Anzahl der Quantilgruppen). Wir müssen entscheiden, wo wir das hinstellen N – G * Boden ( N / G ) < G zusätzliche Werte. Der folgende Code erledigt all dies einfach und übersichtlich:
Obergrenze(Ranking(inVec)/(N Zeile(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 mehrere Gruppen aufgeteilt werden. Um dies zu vermeiden, können wir ersetzen Rangfolge mit Ranglistengleichstand . Ein Beispiel für die vollständige Funktion finden Sie 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;
);
Punkt 2
Es gibt verschiedene Möglichkeiten, Gruppen mit geringer Anzahl zu aggregieren: nach absoluter Anzahl von Beobachtungen, relativer Anzahl von Beobachtungen (z. B. Gruppen mit weniger als 10 % der größten Gruppe), Festlegung der Gesamtzahl der Gruppen usw. Jeweils hat seine Vor- und Nachteile. Um eine flexible Lösung zu bieten, habe ich mich für einen sowohl interaktiven als auch visuellen Ansatz entschieden, der mit einem Balkendiagramm verwaltet wird, das über einen Schieberegler 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, Code zu entwickeln, der schnell war, wenn die Anzahl der Gruppen groß war. Der Einfachheit halber wollte ich mit Datentabellenoperationen und Plattformen arbeiten (mit Automatische Neuberechnung eingeschaltet). Unten finden Sie ein Beispiel dafür, wie dies vorher und nachher aussehen könnte:
Vor

Nach

Im Allgemeinen erstellt dieser Code eine Übersichtstabelle aus den Gruppen und verwendet die Gruppenanzahlen (die N Zeilen Spalte) als Freq Variable. Dadurch entfällt die Notwendigkeit, Werte aus der Originaltabelle zu aktualisieren, die möglicherweise erheblich größer sind. Den Code finden Sie in Aggregate Groups.JSL . In den globalen Variablengruppen wird zusätzlich zu einer Vektorrangfolge der Zählungen (Ränge) eine Liste der ursprünglichen Gruppenwerte aus der Zusammenfassung gespeichert. Durch Bewegen des Schiebereglers wird die Funktion ausgeführt aggregatLowCounts Funktionen, bei denen die Anforderungsanzahl der Gruppen ( nGruppen ) wird basierend auf der Position des Schiebereglers übergeben. Die Anzahl der Gruppen kann einfach 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. „Andere“) gesetzt, während alle anderen Gruppen gleich bleiben. Da die Tabelle sortiert ist, müssen lediglich die Werte ab Zeile 10 geändert werden.
Punkt 3 / Punkt 4
Meine Motivation für diesen Artikel war ein Vorläufer von Artikel 4. Etwas in einem Assoziativen Array (AA) zu finden ist um Welten schneller als es zu verwenden Ort . Erstellen Sie eine AA mit den 209.405 Wörtern aus Wortliste.JMP Auf meinem Computer dauerte es etwas weniger als 12 Sekunden. Die folgende Tabelle zeigt die Zeit, die zum Auffinden einer Liste zufälliger Wörter aus der Tabelle benötigt wird Ort oder ein AA.
N Wörter
|
Loc (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 gegen AA.JSL .
Die Verwendung von AAs als durchsuchbare Datenstrukturen hat Vor- und Nachteile. Der Vorteil ist, dass Sie einem AA-Schlüssel jeden Wert zuordnen können, auch andere AAs. Die Nachteile bestehen darin, dass Schlüssel eindeutig sein müssen (was meiner Meinung nach keine große Sache ist) 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 dies nicht der Fall ist. Das bedeutet nicht, dass wir sie nicht nutzen können; Wir müssen nur etwas geschickter sein. So etwas wie der folgende Code würde funktionieren der im unter Punkt 3 getaggten Beitrag erwähnte Fall . Etwas umständlicher und in manchen Fällen wahrscheinlich langsamer, aber äußerst 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 und Größeres in Angriff nehmen wollte, zum Beispiel ein Wörterbuch mit allen Wörtern erstellen wollte, die in der englischen Übersetzung von „Les Misérables“ vorkommen? Nehmen wir zunächst an, dass ein Wort nur aus alphabetischen Zeichen besteht, einschließlich möglicherweise Buchstaben außerhalb des Standard-ASCII-Zeichensatzes (z. B. solche mit diakritischen Zeichen). Alles andere ist ein Trennzeichen. Die Herausforderung besteht darin, dass wir nicht sicher sind, auf welche begrenzenden 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 verfügt über die perfekten Tools zum Finden der Wörter, die wir zum Erstellen des Wörterbuchs verwenden: Pat Span Und Pat Pause .Wir könnten es gebrauchen Wörter , aber dann müssten wir jedes Element auf eingebettete Trennzeichen überprüfen. Mithilfe des Mustervergleichs 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, sind möglicherweise einige Feinabstimmungen erforderlich, z. B. das Einfügen zusätzlicher Zeichen und das Speichern der Datei in einer anderen Codierung (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 Schwierigkeiten hatte, es zum Laufen zu bringen. Die Textdatei für Les Misérables wurde von heruntergeladen 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>
Hübsch! Der Versuchen ()-Konstrukt, das Sie für das assoziative Array verwenden Einfügen in() könnte schneller sein, als zuerst auf ein vorhandenes Element zu testen.
Als ich jung genug war, um an einem Lesekreis teilzunehmen, durfte einer meiner weitgereisten Freunde eine Passage mit dem Wort vorlesen Yosemite , was mir noch nie begegnet war. Ich erinnere mich, dass ich über seine viersilbige Aussprache erschrocken war und bemerkte, dass der Lehrer angenehm überrascht war.
Jahre später sagte mir jemand, ich könnte es sagen Lahm ist Rob und den Namen des Stücks so richtig nennen, dass er der Aufmerksamkeit entgeht.