Objeto 1
La parte desafiante aquí en el artículo 1 de Desafío 10 no es el código, sino las complejidades en torno a la definición de cuantil. Primero, mantengamos la distribución de cosas independiente y trabajemos con el orden de clasificación de los valores en lugar de los valores directamente. Es decir, clasificamos los valores en orden ascendente y los numeramos según dónde aparecen en ese orden. Tendremos que decidir qué hacer con las corbatas. Podríamos seguir clasificándolos secuencialmente o darles el mismo valor. El inconveniente del primero es que podemos tener el mismo valor apareciendo en más de un grupo. El inconveniente de este último enfoque es que el número de elementos por grupo puede estar menos equilibrado. Estos dos enfoques corresponden a la Clasificación y Empate de clasificación Funciones JSL. No hemos hablado sobre qué valor dar a las corbatas en el segundo enfoque. Podríamos darles a todos el siguiente valor de orden de clasificación secuencial. Alternativamente, podríamos promediar los valores ordenados secuencialmente. En ambos casos, probablemente queramos darle al siguiente valor secuencial no vinculado el rango que habría recibido si no hubiera empates. Empate de clasificación promedia los rangos, y en aras de la simplicidad usaremos esto.
La siguiente pregunta es cómo dividir los grupos. Podríamos intentar dividirlos lo más equitativamente posible. Una forma sencilla de hacer esto sería clasificar los lazos secuencialmente poniendo al menos Suelo ( norte / gramo ) elementos de cada grupo (donde norte es el número total de artículos y gramo es el número de grupos de cuantiles). Tendremos que decidir dónde poner el norte - gramo * Suelo ( norte / gramo ) < gramo valores adicionales. El siguiente código se encarga de todo esto de manera simple y ordenada:
Techo (Clasificación (inVec) / (N Fila (inVec) / cantidad))
dónde inVec es el vector de entrada (columna) y cuantitativo el número de grupos de cuantiles.
El código anterior puede llevar a que los valores vinculados se dividan entre los grupos. Para evitar esto, podemos reemplazar Clasificación con Empate de clasificación . A continuación, se muestra un ejemplo de la función completa:
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;
);
Ítem 2
Hay varias formas diferentes de agregar grupos de conteo bajo: por número absoluto de observaciones, número relativo de observaciones (por ejemplo, grupos con conteos menores al 10% del grupo más grande), fijando el número total de grupos, etc. tiene sus méritos y defectos. Para proporcionar una solución flexible, elegí un enfoque que fuera interactivo y visual, administrado con un gráfico de barras que se podía ajustar mediante un control deslizante. De esta manera, podía mover el control deslizante hacia adelante y hacia atrás hasta encontrar una distribución de grupos que se veía bien. La dificultad radicaba en crear un código que fuera rápido cuando el número de grupos era grande. Para simplificarlo, quería trabajar con plataformas y operaciones de tabla de datos (con Recalc automático encendido). A continuación, se muestra un ejemplo de cómo podría verse esto antes y después:
Antes

Después

En términos generales, este código funciona mediante la creación de una tabla de resumen de los grupos y el uso de los recuentos de grupos (el N filas columna) como Frec variable. Esto evita la necesidad de actualizar los valores de la tabla original, que puede ser considerablemente mayor. El código se puede encontrar en Aggregate Groups.JSL . Una lista de los valores de grupo originales del resumen se almacena en los grupos de variables globales además de un orden de clasificación vectorial de los recuentos (rangos). Al mover el control deslizante, se ejecuta aggregateLowCounts funciones donde la solicitud de número de grupos ( nGroups ) se pasa según la posición del control deslizante. El número de grupos se puede seleccionar fácilmente a partir del vector de rangos. Por ejemplo, si se desean 10 grupos en total, el valor de cualquier grupo original con un rango de 10 o más se establece en el valor del grupo agregado (por ejemplo, "Otro") y todos los demás grupos permanecen iguales. Debido a que la tabla está ordenada, esto simplemente requiere cambiar los valores de la fila 10 en adelante.
Elemento 3 / Elemento 4
Mi motivación para este artículo fue como un precursor del artículo 4. Encontrar algo en una matriz asociativa (AA) es mucho más rápido que usar Loc . Construyendo un AA con las 209,405 palabras de Lista de palabras.JMP tomó un poco menos de 12 segundos en mi computadora. La siguiente tabla muestra el tiempo necesario para encontrar una lista de palabras aleatorias de la tabla utilizando Loc o un AA.
N palabras
|
Loc (seg)
|
Matriz asociativa (segundos)
|
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
|
Para listas de más de 70 palabras, vale la pena construir AA. El código que utilicé para probar estos dos enfoques está en Loc frente a AA.JSL .
Existen ventajas y desventajas en el uso de AA como estructuras de datos de búsqueda. En el lado positivo, puede asociar cualquier valor con una tecla AA, incluidas otras AA. Los inconvenientes son que las claves deben ser únicas (no es gran cosa en mi opción) y, lo que es más importante, el proceso de búsqueda debe aumentarse si los valores de búsqueda no están en la lista de claves. Es decir, la implementación es relativamente fácil cuando todos los valores de búsqueda posibles se conocen a priori, pero un poco más complicado cuando no lo son. Esto no significa que no podamos usarlos; solo tenemos que ser un poco más astutos. Algo como el siguiente código funcionaría para el caso mencionado en el post etiquetado en el ítem 3 . Un poco más engorroso y probablemente más lento en algunos casos, pero extremadamente flexible. Se puede adaptar fácilmente a situaciones en las que el diccionario de búsqueda cambia simplemente modificando el contenido de la matriz asociativa.
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
);
¿Y si quisiera abordar algo un poco más general, más grande, como construir un diccionario de todas las palabras que aparecen en la traducción al inglés de Los Miserables? Comencemos asumiendo que una palabra está formada solo por caracteres alfabéticos, incluidas posiblemente letras fuera del conjunto de caracteres ASCII estándar (por ejemplo, aquellas con signos diacríticos). Todo lo demás es un delimitador. El desafío aquí es que no estamos seguros de qué personajes delimitadores podemos encontrar. Como sabemos qué caracteres componen las palabras, podemos asumir que si no está en la lista, es un delimitador.
La coincidencia de patrones tiene las herramientas perfectas para encontrar las palabras que usaremos para construir el diccionario: Pat Span y Pat Break .Podríamos usar Palabras , pero luego tendríamos que verificar cada elemento en busca de delimitadores incrustados. El uso de la coincidencia de patrones nos permite hacer todo en un solo paso. El código está a continuación. Todo el proceso tomó entre 8 y 9 segundos. Para aplicar el código a un texto diferente, puede ser necesario realizar algunos ajustes, como incluir caracteres adicionales y guardar el archivo en una codificación diferente (utilicé utf-16 para capturar caracteres ASCII extendidos). Estoy en deuda con @Craige_Hales por ayudarme con esto después de que luché para que funcionara. El archivo de texto de Los Miserables se descargó del Proyecto Gutenberg . Puedes encontrarlo aquí .
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>
¡Bonito! los Tratar () construcción que está utilizando para la matriz asociativa Insertar en() podría ser más rápido que probar primero un elemento existente.
Cuando era lo suficientemente joven para estar en un círculo de lectura, uno de mis compañeros de viaje pudo leer un pasaje con la palabra Yosemite , que nunca había encontrado. Recuerdo que me sorprendió su pronunciación de cuatro sílabas y me di cuenta de que el profesor estaba gratamente sorprendido.
Años después, alguien me dijo que podía decir Cojo es Rob y obtenga el nombre de la obra lo suficientemente correcto como para escapar de la atención.