2011-07-13 23 views
41

Estoy intentando limpiar una base de datos que, a lo largo de los años, había adquirido muchos registros duplicados, con nombres ligeramente diferentes. Por ejemplo, en la tabla de empresas, hay nombres como "Some Company Limited" y "SOME COMPANY LTD!".Técnicas para encontrar cerca de registros duplicados

Mi plan era exportar las tablas ofensivas a R, convertir nombres a minúsculas, reemplazar sinónimos comunes (como "limitado" -> "ltd"), eliminar caracteres no alfabéticos y luego usar agrep para ver qué aspecto similar.

Mi primer problema es que agrep solo acepta un único patrón para que coincida, y el bucle sobre cada nombre de compañía para que coincida con los demás es lento. (Algunas mesas para ser limpiados tendrán decenas, posiblemente cientos de miles de nombres para comprobar.)

he mirado muy brevemente en la tm paquete (JSS article), y parece muy potente, pero orientado hacia el análisis de grandes trozos de texto, en lugar de solo nombres.

tengo unas pocas preguntas relacionadas:

  1. es la tm paquete adecuado para este tipo de tarea?

  2. ¿Existe una alternativa más rápida a agrep? (Función Said utiliza el Levenshtein editar distancia que es anecdóticamente lento.)

  3. ¿Hay otras herramientas adecuados en R, aparte de agrep y tm?

  4. ¿Debería incluso estar haciendo esto en R, o debería este tipo de cosa ser hecho directamente en la base de datos? (Se trata de una base de datos Access, así que será más bien evitar tocarlo si es posible.)

+5

relacionada con los [¿Cómo medir la similitud entre las cuerdas?] (http://stackoverflow.com/questions/6044112/r-how-to-measure-similarity-between-strings) –

Respuesta

29

Si acaba de hacer pequeños lotes que están relativamente bien formados, entonces los compare.linkage() o compare.dedup() funciones en el RecordLinkage package debería ser un gran punto de partida. Pero si tienes grandes lotes, entonces es posible que tengas que hacer algunos retoques más.

utilizo las funciones jarowinkler(), levenshteinSim() y soundex() en RecordLinkage a escribir mi propia función que usar mi propio esquema de ponderación (también, como lo es, no se puede utilizar soundex() de grandes conjuntos de datos con RecordLinkage).

Si tengo dos listas de nombres que quiero hacer coincidir ("enlace de registro"), entonces normalmente convierto ambos a minúsculas y elimino toda la puntuación. Para ocuparme de "Limitado" frente a "LTD", generalmente creo otro vector de la primera palabra de cada lista, lo que permite un peso adicional en la primera palabra. Si creo que una lista puede contener acrónimos (tal vez ATT o IBM), yo haré acrónimo de la otra lista. Para cada lista termino con un marco de datos de cadenas que me gustaría comparar que escribo como tablas separadas en una base de datos MySQL.

Así que yo no termino con demasiados candidatos, que LEFT OUTER JOIN estas dos tablas en algo que tiene al partido entre las dos listas (tal vez por las tres primeras letras de cada lista o los tres primeros letras y las primeras tres letras en el acrónimo).Luego calculo las puntuaciones de los partidos usando las funciones anteriores.

Todavía tiene que hacer una gran cantidad de inspección manual, pero puede ordenar el puntaje para descartar rápidamente las incongruencias.

+4

+1 para explicar cómo normalizar el texto. Todo a menudo pasado por alto "primer paso". tolower(), gsub(). Hago algo muy similar mirando el resumen (como.factor (mi_vector)) y viendo lo que no coincide. A veces es realmente muy simple y escribir las líneas puede ser mucho más limpio que tratar de ser elegante con expresiones regulares. –

+2

@AndrewMedico sí, parece que el paquete ya no está activo en CRAN. Puede obtener versiones pasadas del archivo. ¿Estoy obligado a convertirme en el mantenedor del paquete? –

+0

@RichardHerron gracias por señalar los paquetes, ahora está en CRAN. ¿Tiene usted que decidir qué hacer si solo tengo columnas numéricas y difieren por fluctuaciones aleatorias y quiero encontrar coincidencias en datos numéricos? – Richard

9

Tal vez google refine podría ayudar. Parece estar más equipado si tienes muchas excepciones y aún no las conoces todas.

+0

Gracias por señalar esa herramienta. ¡Parece muy útil! –

+0

No he usado Google refine pero me impresionaron los videos. Parece ser bueno para manejar coincidencias difusas y, lo mejor de todo, parece que se puede guardar el código subyacente para que pueda ejecutarse si es necesario nuevamente o si se quiere ejecutar el mismo algoritmo en datos similares. – Farrel

5

Lo que estás haciendo se llama record linkage, y ha sido un gran campo de investigación durante muchas décadas. Afortunadamente para ti, hay un montón de herramientas que están listas para este tipo de cosas. Básicamente, puede apuntarlos a su base de datos, configurar algunos de limpieza y comparadores (como Levenshtein o Jaro-Winkler o ...), y se irán y harán el trabajo por usted.

Estas herramientas generalmente tienen funciones para resolver los problemas de rendimiento, por lo que aunque Levenshtein es lento, pueden funcionar rápido porque la mayoría de los pares de registros nunca se comparan en absoluto.

El enlace de Wikipedia anterior tiene enlaces a varias herramientas de vinculación de registros que puede usar. Personalmente, he escrito uno llamado Duke en Java, que he utilizado con éxito para exactamente esto. Si quiere algo grande y costoso, puede comprar una herramienta de Gestión de Datos Maestros.

Cuestiones relacionadas