如何将数据帧(x)的一列与另一个数据帧(x1,x2,x3,x4,xn)的每n列进行压缩,并计算每对的lev距离



我有一个包含名称和URL的df

data = [
['name1', ''],
['name2', 'name2.com'],
['name3', 'name3.com, name4.com, name5.com' ],
]
df = pd.DataFrame(data, columns=["name", "url"])

我需要计算每个名称和每个url之间的Levenstein距离,url列有时有多个用逗号分隔的url(但不是列表(,我不知道是否以及有多少是预先连接的。有时该栏是空白的。

我正在处理的实际列表有数千行

from Levenshtein import distance as lev

我尝试创建一个单独的df,将"url"列分解并用逗号分隔:

df1 = df['url']
df1 = df1.str.split(',', expand=True)

我不知道如何让它根据df中的名称检查df1中的每一列,所以我对变量进行了硬编码,并在没有列被分解的情况下添加了列


# add columns if they don't exist
df1 = df1[0].to_list()
cols = [0,1,2]
df1 = df1.reindex(df1.columns.union(cols, sort=None), axis=1, fill_value='')

# create variables for each item to compare
name = df['name']
url0 = df1[0]
url1 = df1[1]
url2 = df1[2]
# create list for each calculation
url0_vs_name = []
url11_vs_name = []
url2_vs_name = []

#calculate Levenshtein distance between names and urls
for a, b in zip(name, url0):
url0_vs_name.append(lev(a, b))

for c, d in zip(name, url1):
url1_vs_name.append(lev(c , d))

for e, f in zip(name, url2):
url2_vs_name.append(lev(e , f))

# append results to dataframe
col_list = ['url0_vs_name']
df1 = pd.DataFrame(url0_vs_name, columns=col_list)
df1['url1_vs_name'] = pd.DataFrame(url1_vs_name)
df1['url2_vs_name'] = pd.DataFrame(url2_vs_name)

这是可行的,但我可能在df1中有10列,或者只有1列。是否可以在不指定所有df1列的情况下计算每个名称与每个url并附加结果?

这是我的解决方案:

  1. 首先,带有空url的行被删除,因为我认为在计算levenstein disance时,它们不感兴趣。我用replace和dropna方法实现了删除("inplace=True"是更新同一df上的更改,而不是创建不同的对象(
df.replace("", np.nan, inplace=True)
df.dropna(inplace = True)
  1. 然后,我使用aaply方法,该方法对pandas系列的每个元素(在本例中为url列(执行一个函数。此函数是使用lambda显式定义的。现在,单元格已经转换为列表,列可以被分解,现在您有了一个df,可以逐行比较列中每个元素之间的距离
df['url'] = df['url'].apply(lambda x: x.split(', '))
df.explode('url')

这就是结果:

name        url
1  name2  name2.com
2  name3  name3.com
2  name3  name4.com
2  name3  name5.com

最新更新