Hacer coincidir cadena difusa en Python

Salman Mehmood 10 octubre 2023
  1. Use el módulo thefuzz para hacer coincidir la cadena difusa en Python
  2. Use el módulo proceso para usar la coincidencia de cadenas aproximadas de una manera eficiente
Hacer coincidir cadena difusa en Python

Hoy aprenderemos a usar la biblioteca thefuzz que nos permite hacer coincidencias de cadenas aproximadas en python. Además, aprenderemos a usar el módulo proceso que nos permite unir o extraer cadenas de manera eficiente con la ayuda de la lógica de cadenas difusas.

Use el módulo thefuzz para hacer coincidir la cadena difusa en Python

Esta biblioteca tiene un nombre divertido con la versión anterior porque tenía un nombre específico, que fue renombrado. Así que ahora se mantiene un repositorio diferente; sin embargo, su versión actual se llama thefuzz, así que esto es lo que puedes instalar siguiendo el siguiente comando.

pip install thefuzz

Pero, si miras ejemplos en línea, encontrarás algunos ejemplos con el nombre antiguo, fuzzywuzzy . Por lo tanto, ya no se mantiene ni está desactualizado, pero es posible que encuentre algunos ejemplos con ese nombre.

La biblioteca thefuzz se basa en python-Levenshtei, por lo que debe instalarla con este comando.

pip install python-Levenshtein

Y si tiene algunos problemas durante la instalación, puede usar el siguiente comando, y si nuevamente obtiene un error, puede buscar en Google para encontrar una solución relacionada.

pip install python-Levenshtein-wheels

Esencialmente cadenas de coincidencias aproximadas como el uso de expresiones regulares o la comparación de cadenas a lo largo de dos cadenas. En el caso de la lógica difusa, el valor de verdad de su condición puede ser cualquier número real entre 0 y 1.

Entonces, básicamente, en lugar de decir que algo es “True” o “False”, simplemente le estás dando cualquier valor entre 0 y 1. Se calcula calculando la disimilitud entre dos cadenas en forma de un valor llamado distancia utilizando la métrica de distancia.

Usando la cadena dada, encuentra la distancia entre dos cadenas usando algún algoritmo. Una vez que hayas realizado el proceso de instalación, debes importar fuzz y process desde el módulo thefuzz.

from thefuzz import fuzz, process

Antes de usar fuzz, comprobaremos manualmente la disimilitud entre dos cadenas.

ST1 = "Just a test"
ST2 = "just a test"
print(ST1 == ST2)
print(ST1 != ST2)

Devolverá un valor booleano, pero de forma confusa, obtendrá el percentil de cómo estas cadenas son similares.

False
True

La coincidencia de cadenas difusas nos permite hacer esto de manera más eficiente y más rápida de una manera difusa. Supongamos que tenemos un ejemplo con dos cadenas, y una cadena no es lo mismo con mayúscula J (como se indica arriba).

Si ahora seguimos adelante y llamamos a la función ratio(), que nos da una métrica de similitud, entonces esto nos proporcionará una relación bastante alta que es 91 de 100.

from thefuzz import fuzz, process

print(fuzz.ratio(ST1, ST2))

Producción :

91

Si la cadena es más prolongada, por ejemplo, si no solo cambiamos un carácter sino que cambiamos una cadena completamente diferente, entonces vea lo que devuelve, eche un vistazo.

ST1 = "This is a test string for test"
ST2 = "There aresome test string for testing"
print(fuzz.ratio(ST1, ST2))

Ahora probablemente va a haber alguna similitud, pero va a ser bastante ese 75; esto es solo una proporción simple y nada complicado.

75

También podemos seguir adelante y probar algo como la relación parcial. Por ejemplo, tenemos dos cadenas que queremos determinar su puntuación.

ST1 = "There are test"
ST2 = "There are test string for testing"
print(fuzz.partial_ratio(ST1, ST2))

Usando partial_ratio(), obtendremos el 100% porque estas dos cadenas tienen la misma subcadena (There are test).

En ST2, tenemos algunas palabras diferentes (cadenas), pero no importa porque estamos viendo la relación parcial o la parte individual, pero una relación simple no funciona de manera similar.

100

Digamos que tenemos cadenas que son similares pero tienen un orden diferente; luego, usamos otra métrica.

CASE_1 = "This generation rules the nation"
CASE_2 = "Rules the nation This generation"

Dos casos tienen el texto exacto con el mismo significado de esa frase, pero usar ratio() sería bastante diferente, y usar parcial_ratio() sería diferente.

Si continuamos con token_sort_ratio(), esto sería 100% porque son esencialmente las palabras exactas pero en un orden diferente. Así que esto es lo que la función token_sort_ratio() toma los tokens individuales y los ordena, no importa en qué orden vengan.

print(fuzz.ratio(CASE_1, CASE_2))
print(fuzz.partial_ratio(CASE_1, CASE_2))
print(fuzz.token_sort_ratio(CASE_1, CASE_2))

Producción :

47
64
100

Ahora, si cambiamos una palabra con otra palabra, tendremos un número diferente aquí, pero esencialmente, esta es la razón; no le importa el orden de las fichas individuales.

CASE_1 = "This generation rules the nation"
CASE_2 = "Rules the nation has This generation"

print(fuzz.ratio(CASE_1, CASE_2))
print(fuzz.partial_ratio(CASE_1, CASE_2))
print(fuzz.token_sort_ratio(CASE_1, CASE_2))

Producción :

44
64
94

El token_sort_ratio() también es diferente porque tiene más palabras, pero también tenemos algo llamado token_set_ratio(), y un conjunto contiene cada token solo una vez.

Entonces, no importa con qué frecuencia ocurra; veamos una cadena de ejemplo.

CASE_1 = "This generation"
CASE_2 = "This This generation generation generation generation"

print(fuzz.ratio(CASE_1, CASE_2))
print(fuzz.partial_ratio(CASE_1, CASE_2))
print(fuzz.token_sort_ratio(CASE_1, CASE_2))
print(fuzz.token_set_ratio(CASE_1, CASE_2))

Podemos ver algunas puntuaciones bastante bajas, pero obtuvimos un 100% usando la función token_set_ratio() porque tenemos dos tokens, This y generation existen en ambas cadenas.

Use el módulo proceso para usar la coincidencia de cadenas aproximadas de una manera eficiente

No solo existe el fuzz sino también el proceso porque el proceso es útil y se puede extraer utilizando esta coincidencia aproximada de una colección.

Por ejemplo, hemos preparado un par de elementos de la lista para demostrar.

Diff_items = [
    "programing language",
    "Native language",
    "React language",
    "People stuff",
    "This generation",
    "Coding and stuff",
]

Algunos de ellos son bastante similares, puede ver (lenguaje nativo o lenguaje de programación), y ahora podemos seguir adelante y elegir las mejores coincidencias individuales.

Podemos hacerlo manualmente simplemente evaluando el puntaje y luego eligiendo las mejores opciones, pero también podemos hacerlo con el proceso. Para ello, tenemos que llamar a la función extract() desde el módulo procesar.

Se necesitan un par de parámetros, el primero es la cadena de destino, el segundo es la colección que va a extraer y el tercero es el límite que limita las coincidencias o las extracciones a dos.

Si queremos extraer, por ejemplo, algo como lenguaje, en este caso se eligió lenguaje nativo y lenguaje de programación.

print(process.extract("language", Diff_items, limit=2))

Producción :

[('programing language', 90), ('Native language', 90)]

El problema es que esto no es PNL (procesamiento del lenguaje natural); no hay inteligencia detrás de esto; solo mira el token individual. Entonces, por ejemplo, si usamos programación como la cadena de destino y ejecutamos esto.

La primera coincidencia será lenguaje de programación, pero la segunda será lenguaje nativo, que no será codificación.

Aunque tenemos codificación porque, desde la semántica, la codificación está más cerca de la programación, no importa porque aquí no estamos usando IA.

Diff_items = [
    "programing language",
    "Native language",
    "React language",
    "People stuff",
    "Hello World",
    "Coding and stuff",
]

print(process.extract("programing", Diff_items, limit=2))

Producción :

[('programing language', 90), ('Native language', 36)]

Otro último ejemplo es cómo esto puede ser útil; tenemos una biblioteca masiva de libros y queremos encontrar un libro, pero no sabemos con precisión el nombre o cómo podemos llamarlo.

En este caso, podemos usar extract(), y dentro de esta función, pasaremos fuzz.token_sort_ratio al argumento scorer.

LISt_OF_Books = [
    "The python everyone volume 1 - Beginner",
    "The python everyone volume 2 - Machine Learning",
    "The python everyone volume 3 - Data Science",
    "The python everyone volume 4 - Finance",
    "The python everyone volume 5 - Neural Network",
    "The python everyone volume 6 - Computer Vision",
    "Different Data Science book",
    "Java everyone beginner book",
    "python everyone Algorithms and Data Structure",
]


print(
    process.extract(
        "python Data Science", LISt_OF_Books, limit=3, scorer=fuzz.token_sort_ratio
    )
)

Solo lo estamos pasando; no lo estamos llamando, y ahora, obtenemos el resultado principal aquí, y obtenemos otro libro de ciencia de datos como segundo resultado.

Producción :

[('The python everyone volume 3 - Data Science', 63), ('Different Data Science book', 61), ('python everyone Algorithms and Data Structure', 47)]

Así es como es bastante preciso, y puede ser muy útil si tiene un proyecto en el que tiene que encontrarlo de forma confusa. También podemos usarlo para automatizar sus procedimientos.

Hay recursos adicionales donde puede encontrar más ayuda usando github y stackoverflow.

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn