12 de septiembre de 2010

Aumento en la calidad de datos patronimicos 2: heuristicas

Introducción

En un artículo previo, he definido un algoritmo para detectar el Índice de Coincidencia (IC) entre dos identidades de personas. Estas identidades están formadas por un conjunto de datos arbitrario, como nombres, apellidos, sexo fecha de nacimiento, etc. En el artículo previo, no se especificó cómo eran seleccionadas las idendidades a ser comparadas. En este artículo la idea es definir los conceptos que permitan entender las distintas formas de pre-selección de identidades de forma que las comparaciones no tarden años en ejecutarse, y a la vez permita detectar la mayor cantidad de registros duplicados en una base de datos.


Objetivo

El objetivo final del cálculo del IC entre dos identidades es poder encontrar posibles duplicados en los registros de las personas (sobre todo entre los pacientes). Una vez que se encuentran dos o más registros duplicados, se procede a la unión de esos registros. Esto es esencial para garantizar que los procesos de identificación de personas (en el ámbito de la salud) funcionen correctamente, y para garantizar que el registro clínico se realiza para la persona correcta, y que todos los registros clínicos de esa persona están asignados a una única identidad (si la persona tiene más de una identidad, por tener registros de identidades duplicadas, su información sanitaria estará fragmentada, o sea siempre será incompleta).

Entonces, es necesario ejecutar el algoritmo que detecta coincidencias tomando y comparando de a 2 los registros de las personas en la base de datos de pacientes de una o múltiples instituciones sanitarias. El problema es que si en una base de datos con 1000 pacientes se hacen comparaciones de a 2, se terminan haciendo 1.000.000 (1M) comparaciones. Tal vez 1M comparaciones no sea un gran problema, pero ¿qué pasaría si la base de datos tuviera 1M registros de pacientes?, ¡las comparaciones se disparan a un millón de millones!. En este caso, si cada comparación tarda unos 3 segundos, el total de las comparaciones tardarían unos 95129 años aproximadamente.

El objetivo es claramente bajar ese tiempo de ejecución, pero a la vez garantizar que se encontrarán todos los duplicados en las identidades persentes en la base de datos.

Para lograr esto es necesario disminuir la cantidad de registros a comparar de 2 en 2, por lo que previamente a ejecutar la comparación entre 2 identidades, ejecutaremos una heurística que permita preseleccionar todas las identidades que deben compararse, siendo esta cantidad mucho menor a la cantidad de identidades de personas guardadas en la base de datos.

Debe quedar claro que el único método que garantiza que se encuentran todos los duplicados en una base de datos es comparar 2 a 2 todos los registros de la base, cosa que, como ya mencionamos, es impracticable en bases de datos con muchos registros.

La heurística con la que se consigan encontrar todos los duplicados, será la heurística óptima, pero ninguna heurística puede garantizar esto para cualquier base de datos con identidades de personas. O sea, que la los resultados de aplicar la heurística para preselección de registros, depende de la base de datos. Profundizaré sobre este concepto más adelante.


Metodología

El objetivo de las heurísticas es obtener conjuntos de registros de identidades que "se parecen en algo", pero sin necesidad de ejecutar el Algoritmo de Verificación de Identidades (AVI) para calcular el Índice de Coincidencia entre las identidades. A estos conjuntos de identidades "parecidas" les llamaremos "Clases de Preselección" o solo "CP". De este modo, las compararciones de a 2 identidades usando el AVI, se hacen solo sobre las identidades de cada CP, no sobre todos los registros de identidades.

A continuación voy a mostrar el camino lógico que seguí para ir de una comparación de 2 en 2 sobre todos los registros de una base, hasta la solución final encontrando algunas heurísticas por "sentido común", que luego fueron probadas y funcionaron correctamente.

El peor caso empieza teniendo que comparar todas las identidades de la base, de 2 en 2. Esto se puede representar en un cuadro de doble entrada, donde cada par de entradas señalan una comparación a realizar. En la fig. 1 se puede apreciar este cuadro, y como se realizan todas las comparaciones de 2 en 2, aparece todo pintado de verde (este color indica las comparaciones a realizar).

 Fig. 1: cuadro de comparaciones inicial


La primer optimización es que si se compara la identidad A con la identidad B, no es necesario hacer la comparación de B con A, por lo que se reducen las comparaciones a algo menos que la mitad, ya que también se evitan las comparaciones de A con A, B con B, etc. En la fig. 2, las comparaciones se hacen solo sobre la mitad de los registros.

Fig. 2: se comparan solo la mitad de las identidades


Esta primer optimización reduce la cantidad total de comparaciones pero no cambia el orden o la magnitud de comparaciones a realizar, es decir, si antes había que hacer millones de comparaciones, ahora hay que hacer millones/2. Por lo que si antes tardábamos más de 95000 años en hacer las comparaciones de 1M registros, ahora tardaremos más de 47000 años, cosa que sigue siendo impracticable.

Bien, ahora ¿qué pasaría si tuviéramos algo que nos dijera que comparaciones hacer antes de hacerlas?, podríamos bajar el número total de comparaciones y llevar el tiempo total de ejecución a algo razonable. Hacer esto implica que debemos agrupar identidades "parecidas" pero sin calcular el IC, ya que eso nos llevaría de nuevo al problema inicial. La idea es que el algoritmo que agrupe entidades parecidas en Clases de Preselección, también sea un algoritmo rápido. O sea que el tiempo total de hacer la preselección, más el tiempo total de calcular el IC entre 2 identidades, para todas las identidades de cada CP, sea muchísimo menor al tiempo total de ejecución de la primer optimización que se muestra en la fig. 2.

La idea es bien fácil, primero hay que definir el criterio por el cual se agrupan las identidades en las Clases de Preselección. Los criterios que he utilizado en mis pruebas son:
  1. Agrupar por primer letra del primer nombre
  2. Agrupar por primer letra del primer apellido
  3. Agrupar por fecha de nacimiento:
    1. Total: día, mes y año (no sirve si las fechas tienen errores en alguno de sus 3 campos)
    2. Parcial: solo día y mes, o solo mes y año (es más fuerte ante errores en algún campo de la fecha)

Para el criterio 1, lo que se hace es ordenar todas las identidades por primer nombre y tomar de a X identidades con X arbitrario, tomando como CPs por los registros 1..X, X+1..2X, etc., de esta forma cada CP tendrá solo X registros, siendo X mucho menor a N, con N la cantidad total de registros. Con N=1M y X=200, las comparaciones totales serían 5000 x 200^2 / 2 = 100M (en lugar de 1M de millones!). Igualmente este ejemplo, con cada comparación hecha en 3 segundos, tardaría unos 9 años. Si varía X, se podrá variar la cantidad total de comparaciones necesarias. Obviamente el tiempo de comparación de 2 registros dependerá de la velocidad del hardware y de lo complicado que sea el algoritmo de comparación entre 2 identidades.

En la fig. 3 se visualizan las comparaciones a realizar usando Clases de Preselección. Las flechas indican que hubo un ordenamiento de los registros según algún criterio. Se puede ver claramente que la cantidad total de comparaciones disminuye de forma considerable.

Fig. 3: primer aproximación para encontrar Clases de Preselección


De forma análoga se pueden aplicar otros criterios y obtener CPs alternativas. Un potencial problema es que los registros tengan errores y esos errores repercutan en el criterio que se use para crear las CPs. Por ejemplo, si se usa el criterio de tomar de a X identidades, tal que estén ordenadas por la primer letra del primer nombre, si existen muchos primeros nombres con error de registro en la primer letra, un potencial duplicado puede no ser detectado, ya que las identidades con error en la primer letra del primer nombre van a parar a otra CP. Con esto fundamentamos una afirmación hecha previamente: la heurística o criterio que se utilice para crear las CPs depende de cada base de datos, porque depende de los errores que haya en el registro.

Para conseguir una heurística fuerte ante los errores más comunes en nuestros registros, se pueden optar por dos estrategias:
  1. Hacer un estudio estadístico de los errores más comunes en el registro
  2. Utilizar más de una heurística para calcular los ICs entre las identidades

En mi caso opté por la segunda estrategia. Lo que hice fue calcular el IC para los registros de cada CP creada a partir del criterio de "primer letra del primer nombre", pero luego calculé de nuevo el IC para los CPs creados a partir del criterio "primer letra del primer apellido", de esa forma las comparaciones que se me escaparon en la primer vuelta, por tener errores en el primer nombre, en la segunda vuelta, utilizando el criterio por primer apellido, logro que se comparen. Obviamente, un registro puede tener errores en el primer nombre y en el primer apellido, pero la probabilidad de que esto suceda es menor de que un registro tenga error en el primer nombre o en el primer apellido.

Existe una optimización a este tercer paso, debido a un problema que presenta en los límites de las CPs. Ya que si se ordenan los registros y se toman 2 CPs contiguas, es problable que los últimos registros de la primer CP se parezcan a los primeros registros de la segunda CP, y al no considerar esto, estamos perdiendo duplicados potenciales. Para cubrir esto, lo que se hace es solapar un poco las CPs, así la primer CP calcula el IC entre sus identidades, pero también incluye a las primeras identidades de la segunda CP. En la fig. 4 se muestran las CPs solapadas para evitar que se escapen duplicados en los límites de las CPs.

Fig. 4: Clases de Preselección solapadas para incluir comparaciones de casos límite


Otras heurísticas pueden crearse en base a los datos disponibles, y usarse de forma coplementaria para no dejar registros parecidos afuera de las comparaciones.


Conclusiones

Es necesario crear alguna heurística que permita preseleccionar los registros que luego se van a comparar de 2 en 2, para así bajar los tiempos totales de ejecución.

Vimos que el éxito las heurísticas depende de los errores que se tengan en los registros de datos personales, por este motivo, antes de aplicar una heurística cualquiera para encontrar las CPs, es útil estudiar la base de datos para determinar cuáles son los errores más frecuentes y en cuáles datos. De este modo, podemos encontrar heurísticas que sean fuertes ante esos errores, permitiendo encontrar la mayor cantidad de duplicados posible.

Acompañando a las heurísticas se pueden usar otros métodos para acelerar las comparaciones entre las identidades de cada Clase de Preselección. Por ejemplo, el uso de programación paralela, donde distintos CPs puedan ser procesados en simultáneo, permite acelerar un poco las comparaciones totales, aunque no disminuye el orden de las comparaciones. Por ejemplo, si cada CP tiene 250 identidades, y cada comparación tarda 3 seg., las comparaciones para cada CP serán unas 250*250/2 = 31250 y tardarán unas 26 horas. Si se tienen 4 procesadores en paralelo, el tiempo total de ejecución bajará a unas 6,5 horas.


Espero que se haya entendido la idea, si no, comentan abajo y lo explicamos mejor.

19 de agosto de 2010

Congreso Argentino de Informática y Salud - CAIS2010

En este momento me encuentro preparando algunos trabajos para presentar en el CAIS (http://www.39jaiio.org.ar/cais). Quedan gratamente invitados a las charlas:


Miércoles 1 de setiembre de mañana:
Presentación de mi proyecto de grado de la carrera de Ingeniería en Computación
Traumagen, historia clínica electrónica de trauma, con acceso a estudios imagenológicos digitales.
Temas principales: aplicación de estándares a una HCE, OpenEHR, DICOM, HL7 CDA, CIE 10.


Jueves 2 de setiembre depués del mediodía:
Tutorial sobre OpenEHR
Temas principales: objetivos del estándar, OpenEHR como arquitectura de sistemas de HCE, modelo dual: el conocimiento clínico por fuera de la aplicación de software, el modelo de información clínica y los arquetipos.  Será teórico-práctico, viendo primero algunos conceptos y luego probando herramientas.



Saludos y espero poder verlos por el congreso.

26 de marzo de 2010

Aumento de calidad de datos patronimicos

En el 2009 estuve trabajando sobre un algoritmo para realizar búsquedas de pacientes en un base de datos. Si bien esto es una tarea más que resuelta en muchas instituciones, el objetivo del algoritmo era no solo obtener una lista de datos de personas que se correspondieran con un criterio dado, si no detectar en cuanto se corresponden, de forma de encontrar los registros que más se parezcan a lo que buscamos.

Si bien se logró un algoritmo junto al Subcomité Técnico de Identificación de Personas (STID) de SUEIIDISS (HL7 Uruguay), del que participé en el 2009, yo me concentré en otro problema, el de la calidad de los datos. Si bien podemos pensar en cómo resolver las búsquedas de la mejor forma, si la calidad de los datos en nuestra base de datos es pobre, el resultado de la búsqueda será de poca utilidad, y si se llevara la calidad a niveles óptimos, cualquier mecanismo simple de búsqueda nos ayudaría a encontrar lo que necesitamos, por eso el cambio de enfoque. Dicho sea de paso, aquí se puede obtener una copia del documento logrado en el STID.

El resultado de mi investigación fue un algoritmo que sirve para comparar dos identidades, formadas por los atributos: nombres, apellidos, fecha de nacimiento y sexo de una persona. Cualquier tipo de identificador de la persona no forma parte de su identidad, por eso no se consideran números de documentos nacionales ni otros tipos de identificadores en las identidades. El resultado del algoritmo es un número entre 0 y 1 donde 0 indica coincidencia nula y 1 coincidencia total. Un resultado de 0.85 indica que las identidades coinciden en un 85%.

Este algoritmo fue probado en bases de datos con miles de registros, y los resultados obtenidos son óptimos. Según estos experimentos, las identidades cuya coincidencia supera el 95% corresponden a la misma persona, y la diferencia se debe a que hay errores en los datos, por ejemplo un nombre mal escrito, que en base a mis experimentos, es uno de los casos más frecuentes en los de fuentes de error, por ejemplo una letra faltante o la transposición de letras son de los errores más comunes.

Detrás del algoritmo hay tres ideas muy intuitivas:
  • Distintos datos de la identidad de una persona pesan distinto en la identificación de la misma. Nuestra identidad es lo que nos diferencia de las demás personas, pero distintas partes de esta identidad puede diferenciarnos en mayor o menor medida. No es lo mismo diferenciarse por los nombres que por la fecha de nacimiento, seguramente hayan muchas más personas que nacieron el mismo día que uno, que personas que se llaman igual. Entonces cada atributo de la identidad tiene un peso asociado.
  • No solo pasa que cada atributo pesa distinto en la identificación de la persona, si no que este peso en realidad debería variar dependiendo del valor de los atributos. Por ejemplo, si un apellido es muy común, el peso debería ser menor, y si es un apellido poco usual, su peso debería ser mayor. El algoritmo que considera esta afirmación se llamará "Algoritmo de Verificación de Identidades Avanzado" o "AVI-a", y no será descrito en este artículo.
  • El algoritmo debe comportarse bien ante casos de errores en los datos, es decir que si se comparan dos identidades, y una tiene errores en los datos, el algoritmo debería igualmente detectar la similitud entre las identidades. Es por esto que condiciones de igualdad o igualdad parcial no son útiles para el cálculo del índice de coincidencia porque consideran a los datos como un todo o lo divide en grandes partes, es necesario llegar a un nivel de comparación con granularidad suficiente para que los errores no afecten tanto a las comparaciones.

Descripción del Algoritmo de Verificación de Identidades Básico (AVI-b):

Aquí voy a bajar a un nivel muy técnico, igualmente voy a ir explicando los detalles para que nadie pierda el hilo.

La identidad mínima de una persona, como mencioné antes, está formada por los atributos: nombres, apellidos, sexo y fecha de nacimiento. Vamos a tomar dos identidades id1 e id2 para compararlas según el AVI-b.

// Tipo que define la Identidad
Identidad {
  String nom1
  String nom2
  String ap1
  String ap2
  CodigoSexo sexo
  Fecha fecha_nac
}

// Tipo que define la el código para el sexo según la
// codificación utilizada en HL7 que se puede ver aquí:
CodigoSexo {
  const String MASCULINO = "M"
  const String FEMENINO = "F"
  const String IDENFINIDO = "UN"

  // Debe ser alguna de las constantes definidas previamente
  String codigo

}

// Identidades a comparar, con respectivos sus valores para cada atributo
Identidad id1 = { nom11, nom12, ap11, ap12, sexo1, fecha_nac1 }
Identidad id2 = { nom21, nom22, ap21, ap22, sexo2, fecha_nac2 }


Como se mencionó, una de las ideas detrás del algoritmo es que, cada atributo de la identidad tiene un peso distinto en cuanto a la identificación de la persona. A continuación se especifica el peso de cada atributo en la identificación, donde la regla que deben cumplir estos valores es que deben sumar 1, porque si se tienen todos los atributos de la identidad, estos sirven para identificar a la persona en un 100%. Esto se traduce a que si el peso del primer nombre es 0.175, quiere decir que el primer nombre identifica a una persona en un 17,5%. Los valores aquí propuestos son valores encontrados empíricamente, para los cuales se obtuvo un buen funcionamiento del algoritmo (AVI-b).

// Los pesos deben sumar 1
pesos[nom1] = 0.175
pesos[nom2] = 0.175
pesos[ap1]  = 0.175
pesos[ap2]  = 0.175
pesos[sexo] = 0.1
pesos[fecha_nac] = 0.2



No está de más comentar que si bien los pesos planteados para el algoritmo básico (AVI-b) son constantes, por lo expresado en las ideas que están detrás del algoritmo, para el algoritmo avanzado (AVI-a), estos pesos serían funciones que dependen del valor de cada atributo.

A continuación se especifican los algoritmos de comparación de atributos simples que se utilizan para calcular el índice de coincidencia, que es el resultado del AVI-b. Se plantean dos algoritmos distintos para la comparación de nombres y apellidos, uno para el sexo y otro para la fecha de nacimiento. El primer algoritmo para comparar nombres hace la cuenta de cuantos caracteres coinciden en valor y posición y retorna esta cantidad dividida el largo de la palabra más larga, por lo que se obtiene un resultado en el rango 0..1, con valor 1 cuando los nombres y apellidos coinciden completamente. El segundo algoritmo de comparación de nombres está basado en la distancia de Levenshtein, que calcula cuantos caracteres se le deben agregar a una palabra para hacerla coincidir con otra, por lo tanto si el resultado de Levenshtein es 0 las palabras son la misma. La el índice basado en Levenshtein va a dar resultados más altos cuando haya errores de transposición u omisión de caracteres en alguno de los nombres que se están comparando, mientras que el primer algoritmo va a dar más bajo cuando uno de los nombres que se compara tiene alguna letra de menos. Luego voy a mostrar un ejemplo de esto, así que si no se entendió, luego lo retomaremos.

// Case Insensitive Char by Char:
// comparacion de palabras utilizando indice basado en
// comparacion caracter a caracter.
coin_ci_cbc( String a, String b)
{
   // Se pasa todo a minusculas para comparar
   a = pasar_a_minusculas( a )
   b = pasar_a_minusculas( b )
   int max_len = maxLargo(a, b) // Largo del string mas largo
   int min_len = minLargo(a, b) // Largo de string mas corto
   int coincidencias = 0

   for (i = 0..min_len)
   {
      if ( a[i] == b[i] ) coincidencias ++
   }

   return coincidencias / max_len
}


// Case Insensitive Levenshtein:
// comparacion de palabras utilizando indice basado en distancia de Levenshtein
// Mas info>
// - http://www.levenshtein.net/
// - http://es.wikipedia.org/wiki/Distancia_de_Levenshtein
coin_ci_levens( String a, String b)
{
   // Se pasa todo a minusculas para comparar
   a = pasar_a_minusculas( a )
   b = pasar_a_minusculas( b )

   // Largo del string mas largo
   int max_len = maxLargo(a, b)

   // Calcula el indice basado en la distancia de levenshtein

   return 1 - ( levenshtein(a, b) / max_len )
}

coinSEXO(CodigoSexo s1, CodigoSexo s2)
{
   if (s1.codigo == s2.codigo) return 1
   return 0
}

coinFECHA (Fecha f1, Fecha f2)
{
   if (f1 == f2) return 1
   return 0
}


Por último, el cálculo del Índice de Coincidencia que será resultado del AVI-b, como vemos usamos los pesos y los algoritmos para calcular la comparación de atributos simples. En el ejemplo se utiliza coin_ci_cbc como comparador de nombres, éste se podría cambiar por coin_ci_levens.

IC( id1, id2 ) = pesos[nom1] * coin_ci_cbc(id1.nom1, id2.nom1) +
          pesos[nom2] * coin_ci_cbc(id1.nom2, id2.nom2) +
          pesos[ap1]  * coin_ci_cbc(id1.ap1,  id2.ap1) +
          pesos[ap2]  * coin_ci_cbc(id1.ap2,  id2.ap2) +
          pesos[sezo] * coinSEXO(id1.sexo, id2.sexo) +
          pesos[fecha_nac] * coinFECHA(id1.fecha_nac, id2.fecha_nac)

En la siguiente tabla se puede ver el comportamiento del algoritmo básico (AVI-b) probando con algunos casos donde se toma una identidad y se varía algún dato para verificar cómo esta modificación afecta al Índice de Coincidencia (IC) que obtengo como resultado. Algunas aclaraciones para poder interpretar correctamente los resultados:
  • La identidad ID1 es siempre la misma, la que varía es ID2 en algunos valores.
  • Se hicieron 3 casos de comparación, probando con los dos algoritmos distintos para la comparación de nombres y apellidos.
  • Las filas de igual color corresponden a comparaciones de las mismas identidades pero utilizando algoritmos distintos para la comparación de nombres, es decir: ci_cbc o ci_levens.
  • En las filas 1 y 4, la variación de ID2 con respecto a ID1 es que en el segundo nombre se sacó una letra, la C.
  • En las filas 2 y 5, la variación de ID2 con respecto a ID1 es en la fecha de nacimiento.
  • En las filas 3 y 6, la variación de ID2 con respecto a ID1 es el primer nombre completo, manteniendo todos los otros datos. Este caso se podría dar en hermanos gemelos o mellizos, y el algoritmo debería ayudar a diferenciar entre ellos, si no es así, se debería utilizar la identidad extendida mediante los datos de "indicador de nacimiento múltiple" y "orden de nacimiento" que se describen en el documento del STID.

# IC Algor. ID1 ID1 fecha ID2 ID2 fecha
1
0.86
ci_cbc
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Ana Jaqueline
Gomez Rodriguez
1983-11-22 F
2
0.8
ci_cbc
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Ana Jacqueline
Gomez Rodriguez
1983-11-12 F
3
0.825
ci_cbc
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Carla Jacqueline
Gomez Rodriguez
1983-11-22 F
4
0.9825
ci_levens
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Ana Jaqueline
Gomez Rodriguez
1983-11-22 F
5
0.8
ci_levens
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Ana Jacqueline
Gomez Rodriguez
1983-11-12 F
6
0.895
ci_levens
Ana Jacqueline
Gomez Rodriguez
1983-11-22 F Carla Jacqueline
Gomez Rodriguez
1983-11-22 F
Tabla de resultados


Trabajo futuro:

Si bien se probó empíricamente el buen funcionamiento del Algoritmo de Verificación de Identidades Básico (AVI-b) creo que se podría ajustar aún más el resultado utilizando el algoritmo avanzado, donde los pesos se ajustan según los valores de los atributos de las identidades. Esto sería fácil de hacer si se tienen calculadas las frecuencias de nombres y apellidos de las identidades que se tienen en la base de datos donde están registradas las identidades a verificar, esto quiere decir, calcular cuántas personas tienen cada nombre (Pablo, Pedro, Juan, etc) y dividir cada una de esas cantidades entre el número total de identidades en la base. Luego esa frecuencia sería utilizada para aumentar el peso de un atributo (si es que hay poca frecuencia de ese nombre o apellido), o disminuir el peso de un atributo (si es que hay muchas personas que se llaman igual). Esta técnica ajustaría los valores resultantes de las comparaciones a un porcentaje más ajustado a la realidad. Como puede resultar obvio, los valores de frecuencias se deberían actualizar cada tanto, y con esto logramos un resultado que puede estar oculto a primera vista: el algoritmo se ajusta a las distintas frecuencias de nombres que se dan en distintos momentos. Es sabido que hay épocas donde un nombre se hace muy popular, y en algunos años el nombre más popular cambia, cambiando la frecuencia de personas que podemos encontrar con esos nombres en nuestras bases de datos. Con esto logramos un algoritmo que se adapta automáticamente (algoritmo adaptable) a cambios que se dan en la cultura de la sociedad. ¿Interesante no?


Conclusiones:

Cómo se puede apreciar en las filas 1 y 4 de la tabla de resultados, al cambiar una sola letra de un nombre o un apellido, el IC es mucho más alto usando el algoritmo ci_levens que el ci_cbc para comparar nombres, esto se debe a que el índice que se calcula en base a Levenshtein es más fuerte o se comporta mejor ante pequeños cambios. Este cambio se puede deber a un error humano en el registro, y es bueno tener un algoritmo que lo pueda detectar. Es decir que la detección de duplicados también ayuda a la detección de errores en el registro, y por lo tanto a mejorar la calidad del mismo, que es el objetivo planteado al inicio.

En las filas 2 y 5 no vemos cambio en el resultado del CI porque lo que es distinto entre las identidades es la fecha de nacimiento.

Por último, en las filas 3 y 6 vemos una pequeña diferencia en el CI, esto se debe a que el primer nombre es tan distinto entre ID1 e ID2 que tanto el índice basado en Levenshtein como el índice basado en la cuenta carácter a carácter detectan que ambos nombres son distintos, bajando el valor del CI en cantidades similares.

Espero que se hayan entendido las ideas detrás del algoritmo, cuáles eran los objetivos y que hayan quedado claras las conclusiones. Por cualquier consulta o comentario no duden en agregar un comentario.

19 de diciembre de 2009

Estandares que salvan vidas

Ayer en el hipódromo de Maroñas se lanzó el número cero de la revista 1024, en la cual fue publicado un artículo de quien les escribe estas palabras. Gracias a Enrique González, editor de la revista, por confiar en mi para escribir este artículo y a todos los colegas que participaron y colaboraron en la creación de la misma.

Milveinticuatro, o simplemente 1024, es una revista de informática y tecnología para Uruguay, que viene a llenar un hueco en cuanto a la comunicación de los principales actores vinculados a las TICs el medio local.

Si bien "estándares que salvan vidas" es un título fuerte para un tema tan complicado y complejo como la informatización y estandarización aplicadas a la salud, creo que va a captar la atención del lector. Aquí les dejo el artículo publicado:


Hoy las instituciones de salud son sistemas caóticos, con pocos procesos definidos, con un modelo de registro sumamente heterogéneo y donde existe una enorme necesidad de información por parte de los médicos y los gestores de estas instituciones. Solo pensar en qué los médicos que nos atienden no disponen de toda nuestra información clínica en el momento de la atención, nos hace dudar de la calidad del cuidado que estamos recibiendo, no por los médicos, si no por la falta de información completa y precisa. La única solución a estos problemas es la informatización de la mano de la estandarización.

Los sistemas de información en el ámbito de la salud tienen varias diferencias con los sistemas en otros ámbitos. El dominio de la salud es complejo, cada acto médico es ejecutado por diversos roles, los procesos de atención se adaptan y varían caso a caso, y se manejan una inmensa cantidad de variables y registros.

La Historia Clínica Electrónica (HCE) de un paciente debe ser completa, por lo que debe tener la capacidad de registrar toda la información que surge de cada acto médico durante toda la vida del paciente. Para lograrlo se debe elegir cuidadosamente el modelo de información que se usará para almacenar toda la información clínica, se destacan tres modelos estándar: HL7 CDA [1], ISO/CEN 13606 [2] y OpenEHR [3]. En la figura 1 se muestra un esquema de la relaciones entre estándares, en el sitio de OpenEHR-ES [4] está el análisis de donde se derivan estas relaciones.



Figura 1. Relación entre estándares

HL7 es una organización que desarrolla estándares focalizados en el intercambio de información entre sistemas en salud. HL7 CDA (Clinical Document Architecture) es su estándar para modelar de documentos clínicos. CDA sirve tanto para la comunicación, como para el almacenamiento documental que compone la Historia Clínica Electrónica de un paciente.

ISO/CEN 13606 es un estándar nacido en la Comunidad Europea y hoy en día es estándar mundial ISO. Es también un estándar para modelar documentos clínicos. Existe una compatibilización con CDA haciéndolos intercambiables. El 13606 se basa en el modelo de OpenEHR, simplificándolo de forma sustancial para cumplir específicamente con el objetivo de comunicar de información clínica en formato electrónico.

El modelo de referencia de OpenEHR es uno de los modelos de información clínica más completos y genéricos que existe. Con similitudes al modelo de HL7 y al ISO 13606, OpenEHR define un modelo de información y una arquitectura que soporta la implementación de cualquier HCE, tal que sea completa, segura, única para cada paciente y longitudinal a la vida del paciente. Muchas de las características con las que cumple OpenEHR están definidas en la especificación técnica ISO/TS 18308. Cómo este estándar no es muy conocido en la región, estamos comenzando una comunidad en español sobre OpenEHR [4] para aportar a su difusión.

Las razones de por qué informatizar la Historia Clínica (HC) son varias, desde el logro de la eficacia en la gestión hasta salvar una vida, pasando por mejorar los procesos y la calidad de la atención médica, y por ende, la calidad de vida de la población. Las instituciones tienen serios problemas de gestión por no poder contar con la información completa y precisa de su principal actividad: la atención médica. Como ya sabemos, para gestionar hay que medir y para medir se necesitan datos.

Informatizando la HC y aplicando estándares resolvemos uno de los principales problemas: la fragmentación de la información clínica. Los sistemas informático-clínicos de hoy en día son verdaderas “islas” de información, donde se fragmenta la información del paciente atentando contra el decreto de 30/09/2003 de Historia Clínica Única para cada persona. La información clínica expresada en forma estándar permite que diversos servicios e instituciones de salud estén interconectados. Si en un accidente de tránsito se tiene una persona gravemente herida, el médico pide su HCE a la institución de la que es socio, accediendo a su información clínica, lo cual le  permite dar una mejor atención. Por ejemplo, si el paciente accidentado es alérgico a un medicamento, el médico que lo atiende en la calle lo sabrá, evitándole administrar una droga que lo puede matar.

Algo no muy visto en sistemas de HCE en Uruguay es la geo-referenciación. Imaginemos que una institución tiene a todos sus pacientes ubicados geográficamente, con algunos datos clínicos asociados, como sus “problemas de salud” (diabetes, hipertensión, asma u obesidad), y a cada problema le asocia un color, el resultado es que se podrá ver un mapa con la distribución de problemas de salud de los pacientes de la institución, permitiendo que se tomen acciones de prevención a nivel poblacional, impactando directamente en la calidad de vida de las personas a largo plazo. Con algo tan simple como ver que el 30% de la población atendida es hipertensa, la institución podría lanzar una campaña de control de la presión, y a los pocos meses se puede ver si esa población de riesgo tiene su presión arterial dentro de los rangos normales, logrando prevenir futuros problemas cardíacos.
Con un sistema de este tipo, cuando ocurrió el problema de la plombemia en algunos barrios de Montevideo, se habría detectado de forma temprana las zonas de riesgo y tomado medidas en menor tiempo.


Actualmente en la Universidad de la República, en la carrera de Ingeniería en Computación, estamos trabajando en una tesis de grado: “Historia Clínica Electrónica de Trauma” [6].
Este trabajo lo estamos realizando junto al Dr. Fernando Machado y la encargada del centro de cómputos Lucía Grundel del Hospital Maciel, una de las principales puertas de emergencia con entrada de pacientes traumatizados del Uruguay. Adicionalmente se realizó un adelanto del proyecto final al que se lo denominó “MiniClin”[5].

MiniClin: la HCE minimal
Es un sistema de HCE completa, minimal y estándar. Es completa porque permite integrar todos los tipos de registros que forman la HCE. Minimal porque cuenta con las características mínimas de una HCE: poder registrar datos clínicos y guardarlos en un medio electrónico. Y es estándar porque para el repositorio de documentos clínicos se utiliza HL7 CDA. En octubre de 2009, en el Congreso de Informática Médica Normalizada realizado en Montevideo, se realizó la presentación del trabajo para el que se documentó MiniClin y su aplicación al mundo clínico. Este sistema de código abierto estará disponible en breve y de forma gratuita para todos los médicos de Uruguay.

HCE de Trauma
Es la implementación de la arquitectura propuesta por el estándar OpenEHR, en el cual, como salida hacia otros sistemas clínicos, se generan documentos clínicos CDA.
Junto al registro de información se implementa el proceso de atención del paciente traumatizado, así la aplicación sigue paso a paso las tareas que los médicos van realizando. La generación de CDA tiene dos objetivos, la comunicación de información clínica entre sistemas, y que los documentos clínicos puedan ser firmados electrónicamente, para darle a la HCE la validez legal que tiene un documento en papel.

Otras características de esta HCE es que clasificará los diagnósticos con el estándar internacional de enfermedades definido por al Organización Mundial de la Salud en la versión 10 (CIE10), también integrará el acceso a exámenes imagenológicos digitales adquiridos desde equipos que cumplan con la norma de imagen digital y comunicaciones en medicina (por siglas en inglés, DICOM).

Tanto MiniClin como la HCE de Trauma fueron pensados con la idea de que en el futuro sean los propios médicos quienes definan los formularios para registro en el sistema, así estos registros se adecuarán a las necesidades de los médicos, quitándole una pesada y tediosa tarea de análisis a los informáticos. Esto aporta también a disminuir la barrera cultural entre médicos e informáticos, haciendo a los médicos partícipes activos en el desarrollo de la HCE.

En conclusión, los sistemas que no sigan estándares, tanto en el modelado interno de la información clínica como en su representación para la comunicación, tenderán a desaparecen en los próximos años. Estos sistemas serán islas de información dentro de una institución e irá en contra de sus necesidades de integración interna entre sistemas y externa con otras instituciones. Además, quienes no adopten estándares estarán violando el decreto de Historia Clínica Electrónica única de cada persona, desde el registro perinatal hasta el fallecimiento.


A/C Pablo Pazos Gutiérrez

[A] Tesis de grado en elaboración: “Historia Clínica Electrónica de Trauma” A/C Pablo Pazos, A/C Leandro Carrasco, Tutor: Prof. Franco Simini, Facultad de Ingeniería, UdelaR. 

Referencias

[1] Health Level Seven, Inc

[2] ISO/CEN 13606

[3] OpenEHR, future-proof and flexible EHR System Architecture

[4] OpenEHR-ES: comunidad OpenEHR en español

[5] MiniClin





18 de diciembre de 2009

Informática Clínica y Estándares

Hace un tiempito hice un trabajo resumiendo algunos estándares, dando un poco de contexto, buscando complementariedades, y analizando qué lugar ocupan en el desarrollo de la Historia Clínica Electrónica. Aquí dejo la presentación que hice en las Jornadas de Informática e Investigación Operativa de la Facultad de Ingeniería de Montevideo, espero sea de su agrado.

¡Los comentarios son bienvenidos!