python - 字符串匹配的向量化
问题描述
问题:是否可以对两个 DataFrames/Series 的字符串匹配进行矢量化?
概念:我有两个数据帧(df_address,df_world_city):
- df_address:包含地址数据的列(例如“Sherlock Str.; Paris;”)
- df_world_city:包含城市名称和对应国家(“FRA”、“Paris”)的列
我遍历每个地址并尝试匹配所有城市,以找出地址中提到的城市并将相应的国家添加到其中。匹配的城市保存在一个列表中,该列表是以国家为键的字典的值({'FRA': ['Paris']})。
目前,我主要使用 for 循环来遍历地址和城市以匹配它们。使用多处理(48 个进程)和大量数据(df_address:160,000 行;df_wordl_city:2,200,000 行)大约需要 4-5 天。
def regex_city_matching(target, location):
if type(target) != str or type(location) != str or len(target) <= 3:
# Skip NaN and to short cities
return False
# Match city only as full word, not a substring of another word
pattern = re.compile('(^|[\W])' + re.escape(target) + '($|[\W])', re.IGNORECASE)
result = re.search(pattern, location)
if result:
return True
return False
def city_matching_no_country_multi_dict_simple(self, df_world_city, df_address):
col_names = ['node_id', 'name', 'city_iso']
df_matched_city_no_country = pd.DataFrame(columns=col_names)
for index_city in df_world_city.index:
# Iterate over each city
w_city = df_world_city.at[index_city, 'city']
if type(w_city) != str or len(w_city) <= 3:
# Skip NaN and to short cities
continue
w_country = df_world_city.at[index_city, 'iso']
for ind_address in df_address.index:
if self.regex_city_matching(w_city, df_address.at[ind_address, 'name']):
node_id = df_address.at[ind_address, 'node_id']
address = df_address.at[ind_address, 'name']
if (df_matched_city_no_country['node_id'] == node_id).any():
# append new city / country
ind_append_address = df_matched_city_no_country.loc[df_matched_city_no_country.node_id == node_id].index[0]
if w_country in df_matched_city_no_country.at[ind_append_address, 'city_iso']:
# Country in dictionary
df_matched_city_no_country.at[ind_append_address, 'city_iso'][w_country].append(w_city)
else:
# Country not in dictionary
df_matched_city_no_country.at[ind_append_address, 'city_iso'][w_country] = [w_city]
else:
# add new address with city / country
dict_iso_city = {w_country: [w_city]}
df_matched_city_no_country = df_matched_city_no_country.append(
{'node_id': node_id, 'name': address, 'city_iso': dict_iso_city},
ignore_index=True)
return df_matched_city_no_country
编辑:谢谢@lenik!与一组城市的匹配效率更高,并且完成得非常快。
但它并没有完全实施,因为测试表明误报的数量很高。
解决方案
你应该用 制作一个逆字典{ 'city' : 'COUNTRY', }
,所以你不必循环,只需在恒定(O(1))时间内直接访问。
除此之外,我会创建一个set()
已知城市,所以我不需要遍历任何东西,只需快速查找,我就知道这个城市是否未知。
最后,我会在不使用非常昂贵的正则表达式的情况下简化地址解析,将所有字符转换为大写或小写,用空格替换非字母字符,并且只是.split()
为了获取单词列表而不是你现在正在做的事情。
完成所有这些更改后,处理 200 万个已知城市的 16 万个地址可能需要 10-15 秒。
请告诉我您是否需要代码示例?
推荐阅读
- algorithm - 非常低冲突的非加密散列函数
- reactjs - 为什么必需的字段验证在使用反应的形式中不起作用?
- php - 从 json 解码计数总是显示不同的总和数
- firebase-authentication - 适用于移动应用程序的 Google Identity Platform SAML 设置
- python - 在 pandas 数据框中生成行以弥补一列(或多列)的缺失值
- android - 如何使用 Android Studio 编辑 .aab 文件中的版本
- typescript - “预期 0 个参数,但得到 2 个”,TypeScript 重载
- android - 如何解决“CORS 策略:'Access-Control-Allow-Origin' 标头的值不等于提供的来源。”?
- java - 如何将文本值从 ViewHolder 发送到 ItemTouchHelper 类?
- c++ - C++ - 将文本附加到具有 NTFS“附加数据”权限的文件中