如何无需指定列名批量计算DataFrame中名称与多URL的Levenshtein距离?
批量计算Pandas DataFrame中Name与多列URL的Levenshtein距离
依赖准备
先安装所需库:
pip install pandas python-Levenshtein
解决方案思路
- 自动识别所有URL列:排除
name列,剩余列均视为URL列(若URL列有特定命名规则,比如含url关键字,可调整筛选逻辑) - 对每个URL列,拆分逗号分隔的URL为单独条目
- 计算每个name与对应URL的编辑距离
- 将结果合并回原DataFrame(或生成展开后的明细数据)
代码实现
方案1:保留原行结构,距离与URL一一对应(逗号分隔)
适合需要维持原数据行数的场景:
import pandas as pd from Levenshtein import distance def calc_levenshtein_batch(df, name_col='name'): # 筛选所有URL列(排除name列) url_cols = [col for col in df.columns if col != name_col] for col in url_cols: # 计算每个URL与name的编辑距离,结果用逗号分隔 df[f'{col}_lev_dist'] = df.apply( lambda row: ','.join(str(distance(row[name_col], url.strip())) for url in str(row[col]).split(',') if url.strip()), axis=1 ) # 空URL列对应的距离列设为空字符串 df.loc[df[col].isna() | (df[col] == ''), f'{col}_lev_dist'] = '' return df # 示例使用 sample_data = pd.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'url1': ['alice.com,alice.org', '', 'charlie.net'], 'url2': ['bob.com', 'bob.org,bob.io', None] }) result_df = calc_levenshtein_batch(sample_data) print(result_df)
方案2:展开为明细行,每行对应一组name-URL对
适合需要分析单个URL匹配情况的场景:
import pandas as pd from Levenshtein import distance def expand_and_calc_levenshtein(df, name_col='name'): # 筛选所有URL列 url_cols = [col for col in df.columns if col != name_col] result_rows = [] for idx, row in df.iterrows(): name = row[name_col] for col in url_cols: # 处理空值,拆分URL urls = str(row[col]).split(',') if pd.notna(row[col]) else [] for url in urls: url_clean = url.strip() if url_clean: lev_dist = distance(name, url_clean) result_rows.append({ name_col: name, 'source_url_col': col, 'url': url_clean, 'levenshtein_distance': lev_dist }) result_df = pd.DataFrame(result_rows) # 添加原数据索引,方便关联原表 result_df['original_index'] = df.index.repeat([sum(1 for url in str(row[col]).split(',') if url.strip() for col in url_cols) for idx, row in df.iterrows()]) return result_df # 示例使用 sample_data = pd.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'url1': ['alice.com,alice.org', '', 'charlie.net'], 'url2': ['bob.com', 'bob.org,bob.io', None] }) detail_result = expand_and_calc_levenshtein(sample_data) print(detail_result)
关键说明
- 若URL列命名有规则(比如列名含
url),可修改筛选逻辑为:url_cols = [col for col in df.columns if 'url' in col.lower()] - 空值处理用
str(row[col])避免报错,确保空值被转为字符串 - 如需忽略大小写计算,可将
distance的参数转为小写:distance(row[name_col].lower(), url.strip().lower())
内容的提问来源于stack exchange,提问作者SilviaC
相关产品推荐
相关产品推荐

