Fuzzy Matching en Microsoft Fabric: La solución elegante cuando tus datos "casi" coinciden
- Gabriel Peralta
- 1 abr 2025
- 6 Min. de lectura
Actualizado: 2 abr 2025
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 CSVMientras 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 CSVComo 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 fuzzLlegó 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.
