Cuando comparamos el precio de una habitación de hotel entre diferentes sitios web, debemos asegurarnos de que estamos comparando manzanas con manzanas
En ciencias de la computación, la coincidencia de cadenas difusas es la técnica de encontrar cadenas que coinciden con un patrón aproximadamente (en lugar de exactamente). En otras palabras, la concordancia difusa de cadenas es un tipo de búsqueda que encontrará coincidencias incluso cuando los usuarios escriban mal las palabras o introduzcan sólo palabras parciales para la búsqueda. También se conoce como búsqueda aproximada de cadenas.
La búsqueda difusa de cadenas puede utilizarse en varias aplicaciones, como:
- Un corrector ortográfico y de errores tipográficos. Por ejemplo, si un usuario teclea «Missisaga» en Google, se devuelve una lista de resultados junto con «Showing results for mississauga». Es decir, la consulta de búsqueda devuelve resultados incluso si la entrada del usuario contiene caracteres adicionales o faltantes, u otro tipo de error ortográfico.
- Se puede utilizar un software para comprobar si hay registros duplicados. Por ejemplo, si un cliente aparece varias veces con diferentes compras en la base de datos debido a la diferente ortografía de su nombre (es decir, Abigail Martin frente a Abigail Martínez) una nueva dirección, o un número de teléfono introducido por error.
Hablando de deduplicación, puede que no sea tan fácil como parece, en particular si usted tiene cientos de miles de registros. Incluso Expedia no lo hace 100% bien:
En este post se explicará qué es la concordancia de cadenas difusas junto con sus casos de uso y se darán ejemplos utilizando la librería Fuzzywuzzy de Python.
Cada hotel tiene su propia nomenclatura para nombrar sus habitaciones, el mismo escenario se da en las agencias de viajes online (OTA). Por ejemplo, una habitación en el mismo hotel, Expedia llama «Studio, 1 King Bed with Sofa bed, Corner», Booking.com puede encontrar seguro en mostrar la habitación simplemente como un «Corner King Studio».
No hay nada malo aquí, pero podría llevar a la confusión cuando queremos comparar el precio de la habitación entre OTAs, o una OTA quiere asegurarse de que otra OTA sigue el acuerdo de paridad de tarifas. En otra palabra, para poder comparar el precio, debemos asegurarnos de que estamos comparando manzanas con manzanas.
Uno de los problemas que más frustran a los sitios web y aplicaciones de comparación de precios es tratar de averiguar si dos artículos (o habitaciones de hotel) son para la misma cosa, automáticamente.
Fuzzywuzzy es una biblioteca de Python que utiliza la distancia Levenshtein para calcular las diferencias entre secuencias en un paquete fácil de usar.
Para demostrarlo, creo mi propio conjunto de datos, es decir, para la misma propiedad hotelera, tomo un tipo de habitación de Expedia, digamos «Suite, 1 King Bed (Parlor)», luego lo comparo con un tipo de habitación en Booking.com que es «King Parlor Suite». Con un poco de experiencia, la mayoría de los humanos sabrían que son la misma cosa. Siguiendo esta metodología, creo un pequeño conjunto de datos con más de 100 pares de tipos de habitación que se pueden encontrar en Github.
Usando este conjunto de datos, vamos a probar cómo piensa Fuzzywuzzy. En otras palabras, estamos usando Fuzzywuzzy para emparejar registros entre dos fuentes de datos.
import pandas as pddf = pd.read_csv('room_type.csv')
df.head(10)
El conjunto de datos fue creado por mí mismo, así que, está muy limpio.
Hay varias formas de comparar dos cadenas en Fuzzywuzzy, vamos a probarlas una por una.
-
ratio
, compara la similitud de la cadena completa, en orden.
from fuzzywuzzy import fuzz
fuzz.ratio('Deluxe Room, 1 King Bed', 'Deluxe King Room')
Esto nos dice que el par «Habitación Deluxe, 1 cama King» y «Habitación Deluxe King» son aproximadamente un 62% iguales.
fuzz.ratio('Traditional Double Room, 2 Double Beds', 'Double Room with Two Double Beds')
El par «Habitación Doble Tradicional, 2 camas dobles» y «Habitación Doble con dos camas dobles» son aproximadamente un 69% iguales.
fuzz.ratio('Room, 2 Double Beds (19th to 25th Floors)', 'Two Double Beds - Location Room (19th to 25th Floors)')
El par «Habitación, 2 camas dobles (pisos 19 a 25)» y «Habitación con dos camas dobles – Ubicación (pisos 19 a 25)» son aproximadamente un 74% iguales.
Estoy decepcionado con estos. Resulta que el enfoque ingenuo es demasiado sensible a las diferencias menores en el orden de las palabras, a las palabras que faltan o a las que sobran, y a otros problemas de este tipo.
-
partial_ratio
, compara la similitud parcial de las cadenas.
Seguimos utilizando los mismos pares de datos.
fuzz.partial_ratio('Deluxe Room, 1 King Bed', 'Deluxe King Room')
fuzz.partial_ratio('Traditional Double Room, 2 Double Beds', 'Double Room with Two Double Beds')
fuzz.partial_ratio('Room, 2 Double Beds (19th to 25th Floors)', 'Two Double Beds - Location Room (19th to 25th Floors)')
Para mi conjunto de datos, comparar las cadenas parciales no aporta mejores resultados en general. Continuemos.
-
token_sort_ratio
, ignora el orden de las palabras.
fuzz.token_sort_ratio('Deluxe Room, 1 King Bed', 'Deluxe King Room')
fuzz.token_sort_ratio('Traditional Double Room, 2 Double Beds', 'Double Room with Two Double Beds')
fuzz.token_sort_ratio('Room, 2 Double Beds (19th to 25th Floors)', 'Two Double Beds - Location Room (19th to 25th Floors)')
Mejor hasta ahora.
-
token_set_ratio
, ignora las palabras duplicadas. Es similar con token sort ratio, pero un poco más flexible.
fuzz.token_set_ratio('Deluxe Room, 1 King Bed', 'Deluxe King Room')
fuzz.token_set_ratio('Traditional Double Room, 2 Double Beds', 'Double Room with Two Double Beds')
fuzz.token_set_ratio('Room, 2 Double Beds (19th to 25th Floors)', 'Two Double Beds - Location Room (19th to 25th Floors)')
Parece que token_set_ratio
es el que mejor se ajusta a mis datos. Según este descubrimiento, decidí aplicar token_set_ratio
a todo mi conjunto de datos.