Artículo 1
La parte desafiante aquí en el Punto 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 independiente de las cosas y trabajemos con el orden de rango 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 continuar clasificándolos secuencialmente o darles el mismo valor. El inconveniente de lo 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 de qué valor dar a las corbatas en el segundo enfoque. Podríamos darles a todos el siguiente valor de orden de rango secuencial. Alternativamente, podríamos promediar los valores clasificados secuencialmente. En ambos casos, probablemente queramos dar al siguiente valor secuencial no vinculado el rango que habría recibido si no hubiera vínculos. 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 repartirlos lo más equitativamente posible. Una forma sencilla de hacer esto sería clasificar los lazos secuencialmente poniendo al menos Piso ( norte / gramo ) artículos en cada grupo (donde norte es el número total de artículos y gramo es el número de grupos cuantiles). Tendremos que decidir dónde poner el norte – gramo * Piso ( 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)/quant))
dónde inVec es el vector de entrada (columna) y cuanto el número de grupos de cuantiles.
El código anterior puede llevar a que los valores empatados se dividan en 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;
);
artículo 2
Hay varias maneras diferentes en las que podemos agregar grupos de conteos bajos: por número absoluto de observaciones, número relativo de observaciones (p. ej., grupos con conteos inferiores al 10 % del grupo más grande), fijando el número total de grupos, etc. tiene sus virtudes y defectos. Para brindar una solución flexible, opté por un enfoque que fuera tanto interactivo como 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 viera bien. La dificultad era encontrar un código que fuera rápido cuando el número de grupos era grande. Para simplificar, quería trabajar con operaciones y plataformas de tablas de datos (con Recálculo automático encendido). A continuación se muestra un ejemplo de cómo se vería 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 frecuencia 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 Grupos agregados.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 (clasificaciones). Al mover el control deslizante se ejecuta el agregadoLowCounts funciones donde la solicitud de número de grupos ( nGrupos ) se pasa en función de 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 una clasificación de 10 o mayor se establece en el valor del grupo agregado (p. ej., "Otro") y todos los demás grupos permanecen igual. Debido a que la tabla está ordenada, esto simplemente requiere cambiar los valores desde la fila 10 en adelante.
Artículo 3 / Artículo 4
Mi motivación para este ítem fue como precursor del ítem 4. Encontrar algo en una matriz asociativa (AA) es mucho más rápido que usar ubicación . 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 para encontrar una lista de palabras aleatorias de la tabla utilizando ubicación o un AA.
N palabras
|
Loc (seg)
|
Matriz asociativa (seg)
|
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 el AA. El código que usé para probar estos dos enfoques está en Loc contra 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 clave 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. Esto quiere decir que la implementación es relativamente fácil cuando todos los posibles valores de búsqueda se conocen a priori, pero un poco más complicado cuando no se conocen. 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 la publicación etiquetada en el punto 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 suponiendo que una palabra está formada únicamente por caracteres alfabéticos, incluidas posiblemente letras fuera del conjunto de caracteres ASCII estándar (p. ej., aquellos con signos diacríticos). Todo lo demás es un delimitador. El desafío aquí es que no estamos seguros de qué caracteres delimitadores podemos encontrar. Como sabemos qué caracteres forman las palabras, podemos suponer 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: palmoteo y Pat romper .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á debajo. Todo el proceso tomó entre 8 y 9 segundos. Para aplicar el código a un texto diferente, es posible que sea 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 Les Misérables se descargó de la 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>
¡Lindo! El Intentar () 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 como para estar en un círculo de lectura, uno de mis amigos que había viajado mucho leyó un pasaje con la palabra Yosemite , que nunca había encontrado. Recuerdo que me sobresaltó su pronunciación de cuatro sílabas y noté que el maestro 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 a la atención.