¿Cómo hacer una coincidencia aproximada en la columna del marco de datos de Pandas usando Python?

Prerrequisito: FuzzyWuzzy

En este tutorial, aprenderemos cómo hacer coincidencias aproximadas en la columna de pandas DataFrame usando Python. La coincidencia aproximada es un proceso que nos permite identificar las coincidencias que no son exactas pero que encuentran un patrón determinado en nuestro elemento de destino. La coincidencia aproximada es la base de los motores de búsqueda. Es por eso que recibimos muchas recomendaciones o sugerencias cuando escribimos nuestra consulta de búsqueda en cualquier navegador.

Funciones utilizadas

  • pd.DataFrame (dict): para convertir un diccionario de python en un marco de datos de pandas
  • dataframe[‘column_name’].tolist(): Para convertir una columna particular del marco de datos de pandas en una lista de elementos en python
  • append(): para agregar elementos a una lista
  • process.extract(query, choice, limit): una función que viene con el módulo de procesamiento de la biblioteca fuzzywuzzy para extraer los elementos de la lista de opciones que coinciden con la consulta dada . El número de opciones más cercanas que se extraen está determinado por el límite establecido por nosotros.
  • process.extractOne(query, choice, scorer): extrae la única coincidencia más cercana de la lista de opciones que coincide con la consulta dada y el marcador es el parámetro opcional para que use un marcador particular como fuzz.token_sort_ratio, fuzz.token_set_ratio
  • fuzz.ratio: para calcular la relación de similitud entre dos strings en función de la distancia de Levenshtein
  • fuzz.partial_ratio: para calcular la relación de strings parciales entre la string más pequeña y todas las substrings de longitud n de la string larga
  • fuzz.token_sort_ratio: calcula la relación de similitud después de ordenar los tokens en cada string
  • fuzz.token_set_ratio: intenta descartar diferencias en las strings, devuelve la proporción máxima después de calcular la proporción en tres conjuntos de substrings particulares en python

Ejemplos

Ejemplo 1: (Enfoque básico)

  • Al principio, crearemos dos diccionarios. Luego, lo convertiremos en marcos de datos de pandas y crearemos dos listas vacías para almacenar las coincidencias más tarde de lo que se muestra a continuación:

Python3

from fuzzywuzzy import fuzz
from fuzzywuzzy import process
import pandas
  
dict1 = {'name': ["aparna", "pankaj", 
                  "sudhir", "Geeku"]}
  
dict2 = {'name': ["aparn", "arup", "Pankaj",
                  "sudhir c", "Geek", "abc"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the
# matches later
mat1 = []
mat2 = []
  
# printing the pandas dataframes
dframe1.show()
dframe2.show()

dframe1:

dframe2:

  • Luego, convertiremos los marcos de datos en listas usando la función tolist().
  • Tomamos umbral = 80 para que la coincidencia aproximada ocurra solo cuando las strings están al menos más del 80% cerca entre sí.

Python3

list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 80
threshold = 80

Producción:

  • Luego iteraremos a través de los elementos de list1 para extraer su coincidencia más cercana de list2.
  • Aquí usamos la función process.extract() del módulo de procesamiento para extraer los elementos.
  • Límite = 2 significa que extraerá los dos elementos más cercanos con su relación de precisión, si lo imprimimos ahora, podemos ver los valores de la relación.
  • Luego agregamos cada coincidencia más cercana a la lista mat1
  • Y almacene la lista de coincidencias en la columna ‘coincidencias’ en el primer marco de datos, es decir, dframe1

Python3

# iterating through list1 to extract 
# it's closest match from list2
for i in list1:
    mat1.append(process.extract(i, list2, limit=2))
dframe1['matches'] = mat1
  
dframe1.show()

Producción:

  • Luego iteraremos nuevamente a través de la columna de coincidencias en el ciclo externo y en el ciclo interno iteramos a través de cada conjunto de coincidencias
  • k[1] >= umbral significa que seleccionará solo aquellos elementos cuyo valor de umbral sea mayor o igual a 80 y los agregará a la lista p.
  • Con la función “,”.join(), se unen las coincidencias de elementos separadas por una coma si hay más de una coincidencia para un elemento de columna en particular y se agregan a la lista mat2. Establecemos la lista p vacía nuevamente para almacenar las coincidencias del elemento de la siguiente fila en la primera columna del marco de datos.
  • Luego almacenamos las coincidencias más cercanas resultantes en dframe1 para obtener nuestro resultado final.

Python3

# iterating through the closest
# matches to filter out the
# maximum closest match
for j in dframe1['matches']:
    for k in j:
        
        if k[1] >= threshold:
            p.append(k[0])
              
    mat2.append(",".join(p))
    p = []
      
# storing the resultant matches 
# back to dframe1
dframe1['matches'] = mat2
  
dframe1.show()

Producción:

Ejemplo 2:

En este ejemplo, los pasos son los mismos que en el ejemplo uno. La única diferencia es que hay varias coincidencias para un elemento de fila en particular, como ‘mango’ y ‘choco’. Establecemos el umbral = 82 para aumentar la precisión de la coincidencia aproximada.

Python3

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
  
# creating the dictionaries
dict1 = {'name': ["mango", "coco", "choco", "peanut", "apple"]}
dict2 = {'name': ["mango fruit", "coconut", "chocolate",
                  "mangoes", "chocos", "peanuts", "appl"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the matches later
mat1 = []
mat2 = []
p = []
  
# printing the pandas dataframes
print("First dataframe:\n", dframe1, 
      "\nSecond dataframe:\n", dframe2)
  
# converting dataframe column to list
# of elements
# to do fuzzy matching
list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 82
threshold = 82
  
# iterating through list1 to extract 
# it's closest match from list2
for i in list1:
    mat1.append(process.extract(i, list2, limit=2))
dframe1['matches'] = mat1
  
# iterating through the closest matches
# to filter out the maximum closest match
for j in dframe1['matches']:
    for k in j:
        if k[1] >= threshold:
            p.append(k[0])
    mat2.append(",".join(p))
    p = []
  
  
# storing the resultant matches back to dframe1
dframe1['matches'] = mat2
print("\nDataFrame after Fuzzy matching:")
dframe1

Producción:

Ahora usaremos el método process.extractOne() para hacer coincidir solo el más cercano entre los dos marcos de datos. Dentro de este método aplicaremos diferentes funciones de coincidencia aproximada que son las siguientes:

Ejemplo 3: Usando fuzz.ratio()

Python3

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
  
# creating the dictionaries
dict1 = {'name': ["aparna", "pankaj", "sudhir",
                  "Geeku", "geeks for geeks"]}
  
dict2 = {'name': ["aparn", "arup", "Pankaj",
                  "for geeks geeks", "sudhir c",
                  "geeks geeks"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the matches 
# later
mat1 = []
mat2 = []
p = []
  
# printing the pandas dataframes
print("First dataframe:\n", dframe1,
      "\nSecond dataframe:\n", dframe2)
  
# converting dataframe column to 
# list of elements
# to do fuzzy matching
list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 80
threshold = 80
  
# iterating through list1 to extract 
# it's closest match from list2
for i in list1:
    mat1.append(process.extractOne(i, list2, scorer=fuzz.ratio))
dframe1['matches'] = mat1
  
# iterating through the closest matches
# to filter out the maximum closest match
for j in dframe1['matches']:
    if j[1] >= threshold:
        p.append(j[0])
    mat2.append(",".join(p))
    p = []
  
  
# storing the resultant matches back to dframe1
dframe1['matches'] = mat2
print("\nDataFrame after Fuzzy matching using fuzz.ratio():")
dframe1

Producción:

Ejemplo 4: Usando fuzz.partial_ratio()

Python3

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
  
# creating the dictionaries
dict1 = {'name': ["aparna", "pankaj", "sudhir", 
                  "Geeku", "geeks for geeks"]}
  
dict2 = {'name': ["aparn", "arup", "Pankaj",
                  "for geeks geeks", "sudhir c", 
                  "geeks geeks"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the matches 
# later
mat1 = []
mat2 = []
p = []
  
# printing the pandas dataframes
print("First dataframe:\n", dframe1,
      "\nSecond dataframe:\n", dframe2)
  
# converting dataframe column to 
# list of elements
# to do fuzzy matching
list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 80
threshold = 80
  
# iterating through list1 to extract 
# it's closest match from list2
for i in list1:
    mat1.append(process.extractOne(
      i, list2, scorer=fuzz.partial_ratio))
dframe1['matches'] = mat1
  
# iterating through the closest matches
# to filter out the maximum closest match
for j in dframe1['matches']:
    if j[1] >= threshold:
        p.append(j[0])
    mat2.append(",".join(p))
    p = []
  
  
# storing the resultant matches back to dframe1
dframe1['matches'] = mat2
print("\nDataFrame after Fuzzy matching using fuzz.partial_ratio:")
dframe1

Producción:

Ejemplo 5: Uso de fuzz.token_sort_ratio()

Python3

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
  
# creating the dictionaries
dict1 = {'name': ["aparna", "pankaj", "sudhir", 
                  "Geeku", "geeks for geeks"]}
  
dict2 = {'name': ["aparn", "arup", "Pankaj",
                  "for geeks geeks", "sudhir c",
                  "Geek"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the matches
# later
mat1 = []
mat2 = []
p = []
  
# printing the pandas dataframes
print("First dataframe:\n", dframe1,
      "\nSecond dataframe:\n", dframe2)
  
# converting dataframe column to 
# list of elements
# to do fuzzy matching
list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 80
threshold = 80
  
# iterating through list1 to extract
# it's closest match from list2
for i in list1:
    mat1.append(process.extractOne(
      i, list2, scorer=fuzz.token_sort_ratio))
dframe1['matches'] = mat1
  
# iterating through the closest matches
# to filter out the maximum closest match
for j in dframe1['matches']:
    if j[1] >= threshold:
        p.append(j[0])
    mat2.append(",".join(p))
    p = []
  
  
# storing the resultant matches back 
# to dframe1
dframe1['matches'] = mat2
print("\nDataFrame after Fuzzy matching using fuzz.token_sort_ratio:")
dframe1

Producción:

Ejemplo 6: Uso de fuzz.token_set_ratio()

Python3

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
  
# creating the dictionaries
dict1 = {'name': ["aparna", "pankaj", "Geeku", 
                  "geeks for geeks"]}
  
dict2 = {'name': ["aparn", "arup", "Pankaj",
                  "geeks for for geeks", 
                  "geeks for geeks", "Geek"]}
  
# converting to pandas dataframes
dframe1 = pd.DataFrame(dict1)
dframe2 = pd.DataFrame(dict2)
  
# empty lists for storing the matches
# later
mat1 = []
mat2 = []
p = []
  
# printing the pandas dataframes
print("First dataframe:\n", dframe1,
      "\nSecond dataframe:\n", dframe2)
  
# converting dataframe column 
# to list of elements
# to do fuzzy matching
list1 = dframe1['name'].tolist()
list2 = dframe2['name'].tolist()
  
# taking the threshold as 80
threshold = 80
  
# iterating through list1 to extract
# it's closest match from list2
for i in list1:
    mat1.append(process.extractOne(
      i, list2, scorer=fuzz.token_set_ratio))
dframe1['matches'] = mat1
  
# iterating through the closest matches
# to filter out the maximum closest match
for j in dframe1['matches']:
    if j[1] >= threshold:
        p.append(j[0])
    mat2.append(",".join(p))
    p = []
  
  
# storing the resultant matches back 
# to dframe1
dframe1['matches'] = mat2
print("\nDataFrame after Fuzzy matching using token_set_ratio():")
dframe1

Producción:

Publicación traducida automáticamente

Artículo escrito por rijushree100guha y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *