在Python中映射15,000个城市的有效方法

时间:2019-11-29 12:10:11

标签: python algorithm sorting dataframe

我有大约15,000个观测值的数据集。该观察结果是来自世界各地的城市名称。这个数据集已经被来自许多不同国家的人们所填充,这意味着我用相同的语言用相同的语言重复了几个城市。参见下面的DF提取:

city_name bruselas brussel brussels brussels
brussels auderghem bruxelles bruxelles belgium munchen munchenstein munchwilen munderkingen mundolsheim mungia munguia munich munich
munich
munich germany munich munchen munich rupert mayer strasse

任务是将DF中的所有城市都映射到其英文名称,但是,由于这些城市的格式和语言不同,因此我发现很难找到一种解决方案,除了手动执行此任务外,这是我们要进行15,000多个观察,因此效率不高。最终数据集应如下所示(仅使用上面的一些观察结果):

city_name mapped_city brussels auderghem Brusels bruxelles Brusels bruxelles belgium Brusels munchen Munich
munich germany Munich

任何帮助将不胜感激

3 个答案:

答案 0 :(得分:3)

使用使用Levenshtein distance algorithm

的Fuzzy Wuzzy
import pandas as pd
from fuzzywuzzy import process, fuzz

df = pd.read_clipboard(sep='\t')
print(df.head(5))
0     brussels
1    auderghem
2    bruxelles
3    bruxelles
4      belgium

我们需要一个城市的主列表来用作查找,我假设您知道城市是什么,我将使用github中的这个城市。

cities = pd.read_csv('https://datahub.io/core/world-cities/r/0.csv')

choices = df['City Names'].to_dict()
lookups = cities['name'].tolist()


res = [(lookup,) + item for lookup in lookups for item in process.extract(lookup, choices,limit=2)]
df = pd.DataFrame(res, columns=["lookup", "matched", "score", "idx"])

print(df)
  lookup    matched  score  idx
9401     Munich     munich    100   13
12612    Mungia     mungia    100   10
9400     Munich     munich    100   12
1820   Brussels   brussels    100    0
12613    Mungia    munguia     92   11
...         ...        ...    ...  ...
27205    Желино  auderghem      0    1
27204    Желино   brussels      0    0
27487   Зуунмод  auderghem      0    1
27486   Зуунмод   brussels      0    0
27212    Теарце   brussels      0    0

自然地,如果您事先编辑查找数据框以仅将您知道的城市保留在列表中,那么这将使查找运行更快并返回所需的结果。

例如,e

lookups = ['brussels','munich']

print(df.sort_values('score',ascending=False))
     lookup    matched  score  idx
0  brussels   brussels    100    0
2    munich     munich    100   12
3    munich     munich    100   13
1  brussels  bruxelles     71    2

然后您可以以最高分进行查找。

希望这会为您指明正确的方向。我不是这个库的专家,所以最好仔细阅读您的用例文档以优化代码。 祝你好运。

答案 1 :(得分:3)

您可以只使用Google Maps或OpenStreetMap来搜索那些地方并查看它们返回的内容。两者似乎都能处理带有或不带有国家/地区的不同语言(例如慕尼黑/慕尼黑,北京/北京)的查询,以及某些拼写错误(例如不带“ü”的“ munchen”)。

AFAIK,Google Maps API并非免费使用,但OSM API应该是免费的,在任何情况下,您都可以同时发出GET请求并解析结果。例如,对于OpenStreetMap:

import requests, re, json

lst = {'bruxelles', 'munguia', 'munich rupert mayer strasse', 'munchen', 
       'mundolsheim', 'munchenstein', 'munich', 'brussels', 'munich  germany', 
       'bruselas', 'brussels  auderghem ', 'munderkingen', 'mungia', 
       'munchwilen', 'bruxelles belgium', 'munich  munchen ', 'brussel'}

query = "https://nominatim.openstreetmap.org/search.php?q=%s"
for x in lst:
    response = requests.get(query % x)
    matches = re.findall(r'"placename": (".*?"),', response.text)
    print(x, "-->", json.loads(matches[0]))

结果不完美,例如一些结果过于具体,但您可以使用其他属性,例如“类型”(可能应该是“城市”)。通过一些清理和更多的修补工作,这应该可以帮助您开始。

munich --> München
munderkingen --> Munderkingen
munich  munchen  --> Johanniter-Unfall-Hilfe e.V., Regionalgeschäftsstelle
mungia --> Mungia
brussels  auderghem  --> Auderghem - Oudergem
munchwilen --> Münchwilen
bruselas --> Bruxelles / Brussel
bruxelles --> Bruxelles / Brussel
munguia --> Mungia
munich rupert mayer strasse --> Rupert-Mayer-Straße
mundolsheim --> Mundolsheim
bruxelles belgium --> Bruxelles / Brussel
munchen --> München
brussels --> Bruxelles / Brussel
munchenstein --> Münchenstein
munich  germany --> München
brussel --> Bruxelles / Brussel

对于Google Maps,同样的请求也应如此,但结果似乎不像使用OSM那样容易解析。

(免责声明:如果您向15k这样的请求发送垃圾邮件,不确定它们是否太激动了,您可能希望将其散布开来,或者使用比HTTP请求更多的官方API。您绝对应该缓存的结果两者均完整完成搜索查询(以调整要使用的属性而无需再次查询)以及在用户指定城市重复的情况下映射的城市,以最大程度地减少请求数,从而最大程度地减少服务器负载和运行时间。) / p>

答案 2 :(得分:-1)

尝试按城市的首字母进行映射,以减轻工作量