pandas: calcula la similitud de jaccard para cada fila en función del valor en otra columna

Dec 15 2020

Tengo un marco de datos de la siguiente manera, solo con más filas:

import pandas as pd

data = {'First':  ['First value', 'Second value','Third value'],
'Second': [['old','new','gold','door'], ['old','view','bold','door'],['new','view','world','window']]}

df = pd.DataFrame (data, columns = ['First','Second'])

Para calcular la similitud de jaccard, encontré esta pieza en línea (no es mi solución):

def lexical_overlap(doc1, doc2): 
    words_doc1 = set(doc1) 
    words_doc2 = set(doc2)

    intersection = words_doc1.intersection(words_doc2)
    union = words_doc1.union(words_doc2)
    
    return float(len(intersection)) / len(union) * 100

lo que me gustaría obtener como resultado es que la medida tome cada fila de la Segunda columna como documento y compare cada par de forma iterativa y genere una medida con el nombre de la fila de la Primera columna, algo como esto:

First value and Second value = 80 

First value and Third value  = 95

Second value and Third value = 90

Respuestas

AmitAmola Dec 15 2020 at 23:04

Bueno, lo haría algo así:

from itertools import combinations

for val in list(combinations(range(len(df)), 2)):
    firstlist = df.iloc[val[0],1]
    secondlist = df.iloc[val[1],1]
    
    value = round(lexical_overlap(firstlist,secondlist),2)
    
    print(f"{df.iloc[val[0],0]} and {df.iloc[val[1],0]}'s value is: {value}")

Salida:

First value and Second value's value is: 33.33
First value and Third value's value is: 14.29
Second value and Third value's value is: 14.29
1 QuangHoang Dec 15 2020 at 22:54

Dado que sus datos no son grandes, puede intentar transmitir con un enfoque ligeramente diferente:

# dummy for each rows
s = pd.get_dummies(df.Second.explode()).sum(level=0).values

# pair-wise jaccard
([email protected])/(s|s[:,None,:]).sum(-1) * 100

Salida:

array([[100.        ,  33.33333333,  14.28571429],
       [ 33.33333333, 100.        ,  14.28571429],
       [ 14.28571429,  14.28571429, 100.        ]])