top of page

Fuzzy Matching en Microsoft Fabric: La solución elegante cuando tus datos "casi" coinciden

Actualizado: hace 11 minutos

El dilema de los datos dispares: Cuando "igual" no significa "idéntico"


¿Alguna vez te has encontrado frente a dos conjuntos de datos que deberían encajar perfectamente, pero simplemente no lo hacen? Imagina este escenario: tienes datos de clientes de dos sistemas diferentes. En uno aparece "Ana Torres García, El Ejido" y en el otro "Ana Torres, Ejido". Para ti es evidente que se trata de la misma persona, pero para tu sistema son entidades completamente distintas. Este es el tipo de problema que puede convertir un proyecto de integración de datos aparentemente sencillo en un dolor de cabeza monumental... a menos que conozcas el poder del fuzzy matching


¿Qué es exactamente el Fuzzy Matching?


A diferencia de las comparaciones exactas (donde "Almería" y "Almeria" son tratadas como diferentes), el fuzzy matching evalúa la similitud entre textos, asignando un porcentaje que indica cuán parecidos son. Es como si le dieras a tu sistema la capacidad de decir: "Estos textos son un 95% iguales, probablemente se refieren a lo mismo." En este artículo, te mostraré cómo implementar esta poderosa técnica en Microsoft Fabric para unificar datos que representan la misma información, pero que han sido registrados con ligeras variaciones.


Nuestro caso práctico: Dos listas de contactos que no coinciden


Para este tutorial, trabajaremos con dos archivos CSV que contienen información sobre los mismos contactos, pero estructurados de manera diferente:



Nombre

Primer Apellido

Segundo Apellido

Lugar de Nacimiento

María

González

Pérez

Almería

Juan

Martínez

López

Roquetas de Mar

Ana

Torres

García

El Ejido

Pedro

Hernádez

Sánchez

Adra

Lucía

Fernádez

Díaz

Vícar

Carlos

López

Ruiz

Níjar

Sofía

Pérez

Torres

Huércal-Overa

Miguel

Álvarez

Gómez

Vera

Elena

Sánchez

Moreno

Berja

José

Ruiz

Castro

Carboneras

Tabla 1. Datos del primer archivo CSV

Mientras que en el segundo origen los datos en el csv son los que siguen:



Nombre contacto

Ciudad

María González

Almería

Juan Martínez

Roquetas

Ana Torres

Ejido

Pedro Hernández

Adra

Lucía Fernández

Vícar

Carlos López

Níjar

Sofía Pérez

Huércal

Miguel Álvarez

Vera

Elena Sánchez

Berja

José Ruiz

Carboneras

Tabla 2. Datos del segundo archivo CSV

Como puedes observar, no solo la estructura es diferente, sino que la información misma presenta variaciones: - "Roquetas de Mar" vs "Roquetas" - "El Ejido" vs "Ejido" - "Almería" vs "Almeria" (sin tilde) Además, no existe un identificador único (como un ID de cliente) que permita relacionar ambas fuentes de manera confiable. Es aquí donde el fuzzy matching se convierte en nuestro mejor aliado.

Preparando el entorno en Microsoft Fabric


Antes de sumergirnos en el código, necesitamos configurar nuestro entorno de trabajo en Microsoft Fabric:


Paso 1: Crear un Lakehouse


El Lakehouse nos permitirá almacenar y procesar nuestros archivos CSV de manera eficiente: 1. Accede a tu workspace de Fabric 2. Selecciona "Crear" → "Lakehouse" en la sección "Almacenar datos" 3. Asigna un nombre descriptivo y haz clic en "Crear"


Paso 2: Cargar los archivos CSV


Una vez creado el Lakehouse: 1. Haz clic en "Cargar archivos" 2. Selecciona tus archivos CSV 3. Verifica que los archivos aparezcan en la carpeta "Files" de tu Lakehouse


Paso 3: Crear un Notebook


Para ejecutar nuestro análisis: 1. Vuelve a "Crear" y esta vez selecciona "Notebook" en la sección "Análisis y entrenamiento de datos" 2. Asegúrate de que el lenguaje seleccionado sea "PySpark (Python)" 3. Conecta el notebook a tu Lakehouse desde la opción "Agregar orígenes de datos" ¡Y ya estamos listos para empezar a escribir código!


El código: Haciendo magia con Fuzzy Matching


En primer lugar, deben de instalarse las librerías que se requieran y no disponga el kernel sobre el que se ejecuta el notebook de forma predeterminada. En este caso, se añadirá la librería fuzzywuzzy que proporciona los algoritmos de comparación aproximada:


!pip install fuzzywuzzy

Requirement already satisfied: fuzzywuzzy in /home/trusted-service-user/cluster-env/trident_env/lib/python3.11/site-packages (0.18.0)

A continuación, se cargan las librerías a utilizar: - PySpark.sql.functions para importar funciones que facilitan el procesamiento de los dataframes. - Fuzzywuzzy para realizar la comparación de los datos y obtener porcentajes de equidad.


from pyspark.sql.functions import concat_ws, lower, trim, udf
from fuzzywuzzy import fuzz

Llegó el momento de leer los datos, para lo que se necesita conocer la ruta en la que se encuentran. Dado que se ha conectado el lakehouse al notebook y se utilizará PySpark se puede aprovechar la ruta relativa que ofrece el archivo. Para ello, navegar a la sección Files, clicar sobre el icono de tres puntos (···) asociado al archivo y obtener la ruta relativa para Spark.

ruta_jugadores1 = 'Files/datos_1.csv'
ruta_jugadores2 = 'Files/datos_2.csv'


df1 = spark.read.option("header", "true").csv(ruta_jugadores1)
df2 = spark.read.option("header", "true").csv(ruta_jugadores2)

A continuación, se va a hacer un preprocesamiento de los datos en el que se transformarán en un formato uniforme de manera que la comparación sea lo más eficaz posible:


# Combinar nombre y lugar en una sola cadena
combined_expr1 = concat_ws(" ", df1["Nombre"], df1["Primer Apellido"], df1["Segundo Apellido"], df1["Lugar de Nacimiento"])
combined_expr2 = concat_ws(" ", df2["Nombre contacto"], df2["Ciudad"])

# Generar dataframe combinado de cada origen de datos habiendo convertido todo a minúsculas y limpiando espacios en blanco
df1_combined = df1.withColumn("Combined", lower(trim(combined_expr1)))
df2_combined = df2.withColumn("Combined", lower(trim(combined_expr2)))

En este punto es necesario aclarar qué son lo que se conoce por las siglas UDF dentro del ecosistema de PySpark. Las UDF (User-Defined Functions, o Funciones Definidas por el Usuario) son una característica que permite definir funciones personalizadas en Python y aplicarlas a columnas de un DataFrame de Spark. En este caso, se usan para calcular la similitud entre cadenas con la librería fuzzywuzzy, ya que Spark no tiene una función nativa para fuzzy matching. Aquí es donde realmente brilla nuestra solución. Utilizaremos una udf para calcular la similitud entre las cadenas combinadas:

# Definir UDF para similitud combinada
fuzzy_combined_udf = udf(lambda x, y: fuzz.token_sort_ratio(x, y), IntegerType())

# Cruzar y calcular similitud
matched_df = df1_combined.crossJoin(df2_combined).withColumn(
    "Similarity", fuzzy_combined_udf(df1_combined["Combined"], df2_combined["Combined"])
)

# Filtrar por umbral del 70%
resultado = matched_df.filter(matched_df["Similarity"] > 70).orderBy("Similarity", ascending=False)

# Mostrar resultados
display(resultado)

¿Qué está pasando aquí exactamente? 1. Creamos una función (fuzzy_combined_udf) que utiliza el algoritmo token_sort_ratio para comparar dos cadenas de texto 2. Realizamos un "cross join" para comparar cada fila del primer conjunto con cada fila del segundo 3. Calculamos el porcentaje de similitud para cada par 4. Filtramos aquellos pares que superen el 70% de similitud 5. Ordenamos los resultados por similitud descendente El algoritmo token_sort_ratio es especialmente útil porque considera las palabras como "tokens" independientemente de su orden, lo que permite manejar casos como "Juan Martínez López" vs "Martínez Juan". Con la ejecución del código se obtienen los resultados de la tabla siguiente:



Nombre

Primer Apellido

Segundo Apellido

Lugar de nacimiento

Similarity

Combined

Nombre contacto

Ciudad

Combined

Lucía

Fernández

Díaz

Vícar

90

lucía fernández díaz vícar

Lucía Fernández

Vícar

lucía fernández vícar

Miguel

Álvarez

Gómez

Vera

88

miguel ávarez gómez vera

Miguel Álvarez

Vera

miguel álvarez vera

María

González

Pérez

Almería

86

maría gonzález pérez vera

María González

Almeria

maría gonzález almeria

Carlos

López

Ruiz

Níjar

86

carlos lópez ruiz níjar

Carlos López

Níjar

carlos lopez níjar

Pedro

Hernández

Sánchez

Adra

84

pedro hernández sánchez adra

Pedro Hernández

Adra

pedro hernández adra

Elena

Sánchez

Moreno

Berja

84

elena sánchez moreno berja

Elena Sánchez

Berja

elena sánchez berja

José

Ruiz

Castro

Carboneras

84

josé ruiz castro carboneras

José Ruiz

Carboneras

josé ruiz carboneras

Juan

Martínez

López

Roquetas de Mar

78

juan martinez lópez roquetas de mar

Juan Martínez

Roquetas

juan martínez roquetas

Ana

Torres

García

El Ejido

78

ana torres garcía el ejido

Ana Torres

Ejido

ana torres ejido

Sofía

Pérez

Torres

Huércal-Overa

71

sofía pérez torres huércal-overa

Sofía Pérez

Huércal

sofía pérez huércal

Tabla 3. Resultados de la comparación.

Por último, para completar la gracia de realizar un procesamiento como el mostrado hasta ahora, queda el unificar la información en un solo lugar desde el que se pueda hacer uso. Para ello, creamos una tabla en el Lakehouse relacionado:


# Seleccionar y renombrar columnas para la tabla unificada
tabla_unificada = resultado.select(
    resultado["Nombre"].alias("nombre"),
    resultado["Primer Apellido"].alias("apellido_1"),
    resultado["Segundo Apellido"].alias("apellido_2"),
    resultado["Lugar de Nacimiento"].alias("lugar_nacimiento"),
    resultado["Similarity"].alias("similaridad")
)

# Guardar como tabla en el Lakehouse
tabla_unificada.write.mode("overwrite").format("delta").saveAsTable("Clientes_Unificados")

Más allá del ejemplo básico: Aplicaciones prácticas


Este enfoque puede extenderse a escenarios mucho más complejos:


Deduplicación de bases de datos de clientes


¿Tienes una base de datos con miles de clientes que sospechas contiene duplicados? El fuzzy matching puede ayudarte a identificar entradas como "Javier Rodríguez" y "J. Rodriguez" como potencialmente el mismo cliente.


Integración de catálogos de productos


Cuando necesitas fusionar catálogos de productos de diferentes proveedores donde los nombres de productos varían ligeramente ("iPhone 13 Pro Max 256GB" vs "Apple iPhone 13 Pro Max (256 GB)").


Normalización de dirección geográfica


Para estandarizar referencias geográficas como "Calle Mayor, 5" y "C/ Mayor nº5" o "Barcelona, España" y "BCN, ES".


Mejoras y consideraciones avanzadas


Para implementaciones más sofisticadas, considera: 1. Ajustar el umbral de similitud: El 70% funciona para nuestro ejemplo, pero según tus datos podrías necesitar un valor diferente. 2. Utilizar diferentes algoritmos: Además de token_sort_ratio, la biblioteca fuzzywuzzy ofrece otras funciones como partial_ratio o token_set_ratio que pueden funcionar mejor dependiendo del tipo de variaciones en tus datos. 3. Paralelizar el proceso: Para conjuntos de datos grandes, aprovecha la capacidad de Spark para distribuir el cálculo en varios nodos. 4. Pre-filtrado: Para optimizar rendimiento, puedes implementar un pre-filtrado que reduzca el número de comparaciones necesarias.


Conclusión: El poder de la flexibilidad


En un mundo ideal, todos los sistemas utilizarían identificadores universales y formatos de datos estandarizados. Pero en la realidad empresarial, nos enfrentamos constantemente a la heterogeneidad y las inconsistencias.


El fuzzy matching en Microsoft Fabric nos proporciona una herramienta elegante para navegar este caos de datos, permitiéndonos unificar información valiosa que de otro modo permanecería fragmentada. Esta técnica no solo ahorra tiempo en la limpieza manual de datos, sino que también desbloquea nuevas posibilidades para el análisis integrado y la toma de decisiones.


La próxima vez que te enfrentes a conjuntos de datos que deberían coincidir pero no lo hacen, recuerda: a veces la solución no es forzar la exactitud, sino abrazar la similitud.


Comments


Déjame algún comentario

¡Gracias por contactar!

© 2023 by Power User 365 blog

bottom of page