pandas : 다른 열의 값을 기반으로 모든 행에 대한 jaccard 유사성을 계산합니다.

Dec 15 2020

다음과 같이 더 많은 행만있는 데이터 프레임이 있습니다.

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'])

jaccard 유사성을 계산하기 위해 온라인 에서이 조각을 찾았습니다 (내 솔루션이 아님).

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

결과로 얻고 싶은 것은 측정 값이 두 번째 열의 각 행을 문서로 가져와 각 쌍을 반복적으로 비교하고 다음과 같이 첫 번째 열의 행 이름과 측정 값을 출력하는 것입니다.

First value and Second value = 80 

First value and Third value  = 95

Second value and Third value = 90

답변

AmitAmola Dec 15 2020 at 23:04

글쎄, 나는 다음과 같이 할 것입니다.

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}")

산출:

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

데이터가 크지 않기 때문에 약간 다른 접근 방식으로 브로드 캐스트를 시도 할 수 있습니다.

# 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

산출:

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