Как я могу рассчитать расстояние Левенштейна между всеми строками в двух фреймах данных и вывести оценку Левенштейна для каждой пары? - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь вычислить расстояние Левенштейна между двумя фреймами данных (dfa и dfb), как указано ниже.

dfa:

Name      Addresss     ID  
Name1a    Address1a    ID1a
Name2a    Address2a    ID2a

dfb:

Name      Addresss      ID  
Name1b    Address1b   ID1b
Name2b    Address2b   ID2b

Я понимаю вычисление расстояния между двумя строками, но меня немного смущает, как я могу сопоставить набор столбцов с другим с выводом, который выглядел бы примерно так, с отображением всех пар и оценок:

Вывод:

Name      Name      LevScore
Name1a    Name1b       0.87
Name1a    Name2b       0.45
Name1a    Name3b       0.26
Name2a    Name1b       0.92
Name2a    Name2b       0.67
Name2a    Name3b       0.56
etc

Заранее спасибо!

Mane sh

Ответы [ 2 ]

1 голос
/ 16 июня 2020

Вы можете использовать пакет Levenshtein вместе с itertools, чтобы получить комбинации значений для двух столбцов:

import Levenshtein as lev
from itertools import product

new_df = pd.DataFrame(product(df1['Name'], df2['Name']), columns=["Name1","Name2"])

new_df["LevScore"] = new_df.apply(lambda x: lev.score(x[0],x[1]), axis=1)

print(new_df)

    Name1   Name2   LevScore
0   Name1a  Name1b  1
1   Name1a  Name2b  2
2   Name2a  Name1b  2
3   Name2a  Name2b  1

EDIT

Давайте скажем, это ваш df1:

df1_n = pd.concat([df1,df1,df1]).reset_index(drop=True)
df1_n

Name    Addresss    ID
0   Name1a  Address1a   ID1a
1   Name2a  Address2a   ID2a
2   Name1a  Address1a   ID1a
3   Name2a  Address2a   ID2a
4   Name1a  Address1a   ID1a
5   Name2a  Address2a   ID2a

Как вы сказали, вы можете вычислить комбинации значений, взяв куски размера step из df1_n:

fina_df = pd.DataFrame()
step=2
for i in range(0,df1_n.shape[0],step):
    new_df = pd.DataFrame(product(df1_n.iloc[i:i+step,0], df2['Name']), columns=["Name1","Name2"])
    new_df["LevScore"] = new_df.apply(lambda x: lev.distance(x[0],x[1]), axis=1)
    fina_df = pd.concat([fina_df, new_df], axis=0).reset_index(drop=True)

print(final_df)

Вывод:

Name1   Name2   LevScore
0   Name1a  Name1b  1
1   Name1a  Name2b  2
2   Name2a  Name1b  2
3   Name2a  Name2b  1
4   Name1a  Name1b  1
5   Name1a  Name2b  2
6   Name2a  Name1b  2
7   Name2a  Name2b  1
8   Name1a  Name1b  1
9   Name1a  Name2b  2
10  Name2a  Name1b  2
11  Name2a  Name2b  1

Для вашей ситуации измените 2 на 300 или 500. Это должно избежать переполнения всей вашей оперативной памяти, дайте мне знать, если это работает!

1 голос
/ 16 июня 2020

Попробуйте это:

import pandas as pd
from textdistance import levenshtein
from itertools import product

# dfa = pd.read_clipboard()  # this is just to reproduce your dataframe

# dfb = pd.read_clipboard()  # this is just to reproduce your dataframe

dfc = pd.DataFrame(product(dfa['Name'], dfb['Name']), columns=['Name1', 'Name2'])

dfc['Distance'] = dfc.apply(lambda x: levenshtein.distance(x['Name1'],
                                                           x['Name2']), axis=1)
    Name1   Name2  Distance
0  Name1a  Name1b         1
1  Name1a  Name2b         2
2  Name2a  Name1b         2
3  Name2a  Name2b         1
...