He estado estos días trabajando un poco en el tema de corregir el MiniMult de forma automática con resultados irregulares. De momento me encuentro con ese regustillo a chapuza cuando no haces las cosas como piensas que se deberían hacer. Pero al final funciona, que era de momento el objetivo. Me voy a explicar por partes, comenzando por el final y luego dando saltos como es mi costumbre últimamente (es lo que tiene este cerebro que me ha tocado).
Funcionar, funciona
Como se puede ver en la imagen anterior el sistema devuelve las puntuaciones T del MiniMult corregidas. Ahora explicaré cómo lo he ido haciendo y las chapuzas que he tenido que hacer por el camino.
Obtener las puntuaciones directas
Para obtener las puntuaciones directas lo que debemos hacer primero es contar con unas plantillas que nos permitan saber si cada contestación del sujeto puntúa en una determinada escala. Como ya hablé de cómo había pensado guardarlas en formato de lista sólo voy a repasarlo un poco por encima:
(defvar minimult-plantilla
'(
("L" 11 "F" 1) ... ("L" 53 "F" 1)
("F" 9 "V" 1) ... ("F" 71 "V" 1)
("K" 11 "F" 1) ... ("K" 70 "F" 1)
("Hs" 1 "F" 1) ... ("Hs" 62 "F" 1)
("D" 1 "F" 1) ... ("D" 65 "F" 1)
("Hy" 1 "F" 1) ... ("Hy" 62 "F" 1)
("Pd" 3 "F" 1) ... ("Pd" 71 "V" 1)
("Pa" 5 "V" 1) ... ("Pa" 68 "V" 1)
("Pt" 2 "F" 1) ... ("Pt" 68 "V" 1)
("Sc" 3 "F" 1) ... ("Sc" 66 "V" 1)
("Ma" 4 "V" 1) ... ("Ma" 60 "V" 1)
("Si" 13 "V" 1) ... ("Si" 70 "V" 1)
)
"Plantilla de corrección con valores posicionales.
1. Nombre de escala
2. Número de pregunta
3. Valor puntuable
4. Cantidad de puntos si coincide la respuestas con el valor puntuable.")
En el código de la definición de la variable minimult-plantilla
he
puesto sólo la primera y la última de las respuestas de cada
escala. Ponerlo todo sería confuso y no aportaría nada. Para saber el
resto basta con repasar la serie sobre el MiniMult y se encontrará
una tabla con la plantilla. Luego el código que corrige el test
recorrerá esta variable de principio a fin comprobando y guardando las
coincidencias para obtener las puntuaciones directas.
;; Recorrer toda la plantilla en un bucle while
(let ((contador 0)
(largo-plantilla (length minimult-plantilla))
(escala "")
(pregunta 0)
(respuesta "-")
(valor 0)
(elemento '()))
(while (< contador largo-plantilla)
;; Obtener la plantilla y sus valores
(setq elemento (nth contador minimult-plantilla))
(setq escala (nth 0 elemento))
(setq pregunta (nth 1 elemento))
(setq respuesta (nth 2 elemento))
(setq valor (nth 3 elemento))
;; Poner el contador de la escala a 0
(if (null (lax-plist-get minimult-resultados escala))
(setq minimult-resultados (lax-plist-put minimult-resultados escala 0)))
;; Sumar el VALOR a los resultados para ESCALA si procede
(if (equal (substring minimult-respuestas (1- pregunta) pregunta) respuesta)
(lax-plist-put minimult-resultados escala
(+ (lax-plist-get minimult-resultados escala) valor)))
;; Avanzar a la siguiente entrada de la plantilla
(setq contador (1+ contador)))
...)
Básicamente el bucle while
recorre toda la plantilla, comprueba si
hay un valor para la escala en los resultados, comprueba si la
respuesta del sujeto en la posición que dice esa entrada de la
plantilla coincide con la plantilla y si es así, le suma el valor
que dice la plantilla a la escala
. Todo lo guarda en una lista de
propiedades (plist
) que se llama minimult-resultados
.
Esta parte del código creo que fácilmente entendible por cualquiera que lo lea y no le daré más vueltas.
Convertir puntuaciones directas
Uno de los problemas del MiniMult resulta de resumir el número de preguntas que hay para cada escala. Eso hace que haya que convertir las puntuaciones directas obtenidas en él, a las puntuaciones directas que se hubieran obtenido en el MMPI-2 para poder continuar con la corrección normal del test.
Cuando se corrige el MiniMult a mano, encontramos una tabla de conversión entre puntuaciones. En lugar de utilizar esa tabla me he decidido por hacer un cálculo. Sabiendo el máximo de puntos que se pueden obtener en la escala reducida y en la escala completa se aplica una sencilla fórmula:
Nf = Ntmax × ( Nd / Ndmax )
donde la Nf es la nota estimada en el test, Ntmax es la máxima nota que se podría obtener en el test, Nd es la puntuación obtenida por el sujeto y Ndmax la máxima que podría obtener en el MiniMult. Los valores sobre los que se ha calculado la prueba (creo que ya la he puesto otra vez por aquí) son los siguientes:
Escala | Ntmax | Ndmax |
---|---|---|
L | 15 | 4 |
F | 60 | 13 |
K | 30 | 16 |
Hs | 32 | 12 |
D | 57 | 19 |
Hy | 60 | 22 |
Pd | 50 | 18 |
Pa | 40 | 14 |
Pt | 48 | 15 |
Sc | 78 | 17 |
Ma | 46 | 11 |
Si | 67 | 9 |
Esta parte del código la he dividido en dos partes, una que aplica la fórmula y otra que la va llamando para convertir cada puntuación.
(defun minimult-convertir-MMPI (puntos mmpi minimult)
"Convierte PUNTOS a puntuaciones directas del MMPI-2."
(fround (* mmpi (/ puntos minimult))))
(defun minimult-convertir-directas ()
"Convierte las puntuaciones directas de las escalas."
(lax-plist-put minimult-resultados "L"
(minimult-convertir-MMPI (lax-plist-get minimult-resultados "L")
15.0 4.0))
...
(minimult-convertir-MMPI (lax-plist-get minimult-resultados "Si")
67.0 9.0)))
Para convertir las puntuaciones directas hago una llamada para cada escala. Me hubiera gustado hacer algo más presentable, como guardar las puntuaciones en un diccionario pero me he encontrado con algunos problemas y bugs por mis actuales carencias con Lisp. Al final opté por lo más fácil, pero lo menos flexible y lo más chapucero.
Como se puede apreciar las llamadas las realizo añadiendo a los
valores una parte decimal. Lisp tiene por costumbre mantener el tipo
de las variables cuando realiza cálculos. Si le pasas a la división
enteros sólo devolverá la parte entera de la división, pero en este
caso necesitamos que realice los cálculos con decimales y luego
redondee a entero con fround
.
Ajustar las escalas con K
Una vez obtenidas las puntuaciones directas estimadas se realiza el ajuste K de las puntuaciones de las escalas que lo necesitan, que son las siguientes:
Hs → 0.5 K
Pd → 0.4 K
Pt → 1 K
Sc → 1 K
El código queda así:
(defun minimult-corregir-K (factor-K)
"Añade factor de corrección K a las escalas que lo necesitan."
(lax-plist-put minimult-resultados "Hs"
(fround (+ (lax-plist-get minimult-resultados "Hs")
(* 0.5 factor-K))))
(lax-plist-put minimult-resultados "Pd"
(fround (+ (lax-plist-get minimult-resultados "Pd")
(* 0.4 factor-K))))
(lax-plist-put minimult-resultados "Pt"
(fround (+ (lax-plist-get minimult-resultados "Pt")
factor-K)))
(lax-plist-put minimult-resultados "Sc"
(fround (+ (lax-plist-get minimult-resultados "Sc")
factor-K))))
La llamada a corregir las puntuaciones directas con el factor K se realiza de la siguiente forma:
(minimult-corregir-K (lax-plist-get minimult-resultados "K"))
Y con estos pasos ya hemos obtenido las puntuaciones directas estimadas en el test.
Calcular las puntuaciones T
Al final hay que calcular las puntuaciones T, pero teniendo en cuenta que las puntuaciones se agrupan de forma distinta para hombres y mujeres. Para ello he hecho dos funciones distintas, aunque originalmente estaba pensado una sola que tomara los valores correspondientes de una variable u otra teniendo en cuenta el sexo.
El código es el siguiente:
(if (equal (org-entry-get (point) "Sexo" t) "Hombre")
(minimult-calcular-T-hombre)
(minimult-calcular-T-mujer))
Igual que hice para convertir las puntuaciones de MiniMult se aplica la fórmula
Nt = Ntmin + (Ntmax - Ntmin) × (Nd - Ndmin) / (Ndmax - Ndmin)
Donde Nt son las puntuaciones T y las Nd son las puntuaciones directas. El cálculo se realiza en la función siguiente:
(defun minimult-calcular-T (puntos max-t min-t max-d min-d)
"Convierte PUNTOS a puntuaciones T."
(fround (+ min-t (* (- max-t min-t) (/ (- puntos min-d) (- max-d min-d))))))
y luego se le llama desde otras funciones para convertir las
puntuaciones de mujeres y hombres similares a como hice la función
minimult-convertir-directas
, con los valores que se explican en el
siguiente punto.
Tablas, sexo y rock'and roll
Cuando corriges a mano el MMPI manejas muchas tablas que convierten las puntuaciones. Tablas de corrección de K, tablas de conversión de puntuaciones directas → T para hombres y mujeres.
Observando esas tablas se observa que la distribución de las puntuaciones es homogénea. Sin embargo, están limitadas y en el manual de corrección sólo figuran las puntuaciones entre 30T y 120T y no siempre la puntuación mínima es 0. Y tampoco siempre la puntuación máxima que se puede obtener en la escala está por debajo de 120. Por eso, me decanté en calcular la puntuación en lugar de crear unas larguísimas tablas.
La primera fórmula que he puesto en este post es un caso particular de la fórmula que he mostrado en el punto anterior. El caso particular de que las dos puntuaciones mínimas son 0.
Mirando las puntuaciones en las tablas del manual del MMPI-2, los valores serían los siguientes:
Para varones:
Escala | máx.T | min.T | máx.D | min.D |
---|---|---|---|---|
L | 92 | 30 | 15 | 0 |
F | 120 | 36 | 47 | 0 |
K | 83 | 31 | 30 | 6 |
Hs | 102 | 31 | 38 | 6 |
D | 120 | 30 | 57 | 12 |
Hy | 119 | 31 | 56 | 13 |
Pd | 120 | 31 | 57 | 15 |
Pa | 118 | 30 | 35 | 4 |
Pt | 120 | 30 | 71 | 18 |
Sc | 119 | 30 | 84 | 16 |
Ma | 118 | 31 | 49 | 12 |
Si | 98 | 30 | 69 | 10 |
Para mujeres:
Escala | máx.T | min.T | máx.D | min.D |
---|---|---|---|---|
L | 94 | 30 | 15 | 0 |
F | 119 | 35 | 38 | 0 |
K | 86 | 31 | 30 | 6 |
Hs | 100 | 30 | 38 | 7 |
D | 113 | 30 | 57 | 14 |
Hy | 119 | 31 | 57 | 14 |
Pd | 120 | 31 | 56 | 15 |
Pa | 119 | 32 | 36 | 5 |
Pt | 119 | 31 | 74 | 20 |
Sc | 120 | 30 | 83 | 17 |
Ma | 120 | 31 | 50 | 11 |
Si | 97 | 30 | 69 | 11 |
Si comparamos las dos tablas vemos que las puntuaciones son muy parecidas pero no iguales.
Al final, y como todas las puntuaciones que se manejan son siempre en forma de enteros, aunque todos los cálculos se han realizado en con decimales, se han ido redondeando al entero más cercano siempre y al final al convertirlas en cadena para guardarlas en la lista de propiedades del org se utiliza la siguiente instrucción:
(defun minimult-guardar-resultados (lista-escalas)
"Guarda la LISTA-ESCALAS por pares (propiedad valor)."
(when lista-escalas
(org-entry-put (point) (pop lista-escalas) (format " %d" (pop lista-escalas)))
(minimult-guardar-resultados lista-escalas)))
En entrada org se guarda la escala y con una cadena de formato
" %d"
se convierte la puntuación a cadena truncando la parte decimal
(que en todos los casos, dado el redondeo que se ha venido haciendo,
es .0
).
Cosas mejorables y dificultades
No soy nada productivo con el código en elisp. Aún no domino el lenguaje, ni sus usos y costumbres. Su forma de guardar variables temporales, el que muchas veces se me olvida el quote al definir listas y que los cálculos matemáticos utilizan notación prefija me dificultan muchas veces avanzar. Cometo muchos errores aún y todavía cuando salta el error y me muestra el depurador la pila de llamadas, me cuesta un momento comprender cuál es el error y dónde debo buscarlo.
Cuando me encuentre más suelto con el lenguaje y el entorno, quizá haría las cosas de otras formas más elegantes.
Por algún sitio he leído eso de que Lisp es un lenguaje de programación programable y que puede simular ser otra cosa. En este caso con Emacs estaría simulando que es un editor cuya interface, datos y acciones se enfocan en el texto. Algunos dirían algo parecido sobre AutoCAD y el dibujo técnico.
Llegados a este punto vamos a ver cómo avanza el proyecto: ¿seré capaz de hacer que Emacs, que básicamente es texto, dibuje el perfil gráfico del test? ... Alguna idea llevo de cómo se podría hacer y voy a ver si consigo hacerlo. A pesar de todas mis dificultades y carencias, cada vez me encuentro más cómodo con el lenguaje y el entorno.