Сходство косинуса между столбцами двух фреймов данных разной длины?

У меня есть текстовый столбец в df1 и текстовый столбец в df2. Длина df2 будет отличаться от длины df1. Я хочу вычислить косинусное сходство для каждой записи в df1[текст] по отношению к каждой записи в df2[текст] и дать оценку для каждого совпадения.

образец ввода

df1                           
mahesh                 
suresh


df2                                                                                  
surendra    
mahesh    
shrivatsa    
suresh    
maheshwari

образец вывода

mahesh    surendra       30
mahesh    mahesh         100
mahesh    shrivatsa      20
mahesh    suresh         60
mahesh    maheshwari     80
suresh    surendra       70
suresh    mahesh         60
suresh    shrivatsa      40
suresh    suresh         100
suresh    maheshwari     30

У меня возникли проблемы (получение ключевых ошибок), когда я пытался сопоставить эти два столбца на предмет схожести с использованием подхода tf-idf, поскольку эти столбцы имели разную длину. есть ли другой способ решить эту проблему... Любая помощь будет очень приветствоваться. Я много искал и обнаружил, что почти во всех случаях люди сравнивали первый документ с остальными документами в том же корпусе. здесь это похоже на сравнение каждого документа корпуса 1 с каждым документом корпуса 2.

1 ответ

Существует множество различных мер длины струны. Я не знаю, как использовать косинусное сходство для этого случая, но предлагаю изучить strsim библиотека.

Я дам вам пример того, как я подхожу к проблеме, используя Jaro-Winkler метрика, которая лучше всего подходит для коротких струн.

Кроме того, я включаю свою попытку использовать cosine similarity учитывая пример из документации указанной библиотеки.

Это может быть совершенно неверно, но должно дать вам общее представление о том, как создать фрейм данных из декартова произведения двух столбцов разной длины, а также о том, как применять strsimалгоритмов к данным, хранящимся в pd.DataFrame


Подготовка данных:

import pandas as pd

from similarity.jarowinkler import JaroWinkler
from similarity.cosine import Cosine


df1 = pd.DataFrame({
    "name": ["mahesh", "suresh"]
})

df2 = pd.DataFrame({
    "name": ["mahesh", "surendra", "shrivatsa", "suresh", "maheshwari"]
})

df = pd.MultiIndex.from_product(
    [df1["name"], df2["name"]], names=["col1", "col2"]
).to_frame(index=False)

возвращает:

     col1        col2
0  mahesh      mahesh
1  mahesh    surendra
2  mahesh   shrivatsa
3  mahesh      suresh
4  mahesh  maheshwari
5  suresh      mahesh
6  suresh    surendra
7  suresh   shrivatsa
8  suresh      suresh
9  suresh  maheshwari

Яро-Винклер:

jarowinkler = JaroWinkler()
df["jarowinkler_sim"] = [jarowinkler.similarity(i,j) for i,j in zip(df["col1"],df["col2"])]

возвращает:

    col1    col2        jarowinkler_sim
0   mahesh  mahesh      1.0
1   mahesh  surendra    0.4305555555555555
2   mahesh  shrivatsa   0.5185185185185185
3   mahesh  suresh      0.6666666666666666
4   mahesh  maheshwari  0.9466666666666667
5   suresh  mahesh      0.6666666666666666
6   suresh  surendra    0.8333333333333334
7   suresh  shrivatsa   0.611111111111111
8   suresh  suresh      1.0
9   suresh  maheshwari  0.48888888888888893


Косинусное сходство:

cosine = Cosine(2)
df["p0"] = df["col1"].apply(lambda s: cosine.get_profile(s)) 
df["p1"] = df["col2"].apply(lambda s: cosine.get_profile(s)) 
df["cosine_sim"] = [cosine.similarity_profiles(p0,p1) for p0,p1 in zip(df["p0"],df["p1"])]

df.drop(["p0", "p1"], axis=1)

возвращает:

    col1    col2        cosine_sim
0   mahesh  mahesh      0.9999999999999998
1   mahesh  surendra    0.0
2   mahesh  shrivatsa   0.15811388300841897
3   mahesh  suresh      0.3999999999999999
4   mahesh  maheshwari  0.7453559924999299
5   suresh  mahesh      0.3999999999999999
6   suresh  surendra    0.5070925528371099
7   suresh  shrivatsa   0.15811388300841897
8   suresh  suresh      0.9999999999999998
9   suresh  maheshwari  0.29814239699997197

Другие вопросы по тегам