原文:
www.kdnuggets.com/2022/11/geocoding-python-complete-guide.html
照片由Andrew Stutesman在Unsplash上提供
在处理大数据集进行机器学习时,你是否遇到过看起来像这样的地址列?
图片由作者提供
位置数据可能非常混乱且难以处理。
编码地址很困难,因为它们的基数非常高。如果你尝试使用像独热编码这样的技术对这样的列进行编码,会导致高维度,并且你的机器学习模型可能表现不佳。
克服这个问题的最简单方法是地理编码这些列。
地理编码是将地址转换为地理坐标的过程。这意味着你将把原始地址转换为纬度/经度对。
有许多不同的库可以帮助你用 Python 完成这项工作。最快的是Google Maps API,如果你需要在短时间内转换超过 1000 个地址,我推荐使用它。
然而,Google Maps API 并不是免费的。你需要为每 1000 个请求支付约$5。
Google Maps API 的一个免费替代方案是 OpenStreetMap API。然而,OpenStreetMap API 的速度较慢,且准确性稍差。
在这篇文章中,我将带你通过这两个 API 的地理编码过程。
首先使用 Google Maps API 将地址转换为纬度/经度对。你需要首先创建一个 Google Cloud 账户,并输入你的信用卡信息。
尽管这是一个付费服务,但 Google 在你第一次创建 Google Cloud 账户时会提供$200 的免费信用。这意味着在收费之前,你可以使用他们的地理编码 API 大约 40,000 次。只要你没有达到这个限制,你的账户将不会被收费。
首先,设置一个免费的账户在 Google Cloud 上。然后,一旦你设置了账户,你可以跟随这个教程获取你的 Google Maps API 密钥。
一旦你获得了 API 密钥,就可以开始编码了!
我们将使用Zomato 餐馆 Kaggle数据集进行本教程。确保将数据集安装在你的路径中。然后,使用以下命令安装 googlemaps API 包:
pip install -U googlemaps
运行以下代码行来导入你需要开始的库:
pip install -U googlemaps
现在,让我们读取数据集并检查数据框的前几行:
data = pd.read_csv('zomato.csv',encoding="ISO-8859-1")
df = data.copy()
df.head()
图片作者提供
这个数据框有 21 列和 9551 行。
我们只需要address列进行地理编码,所以我将删除所有其他列。然后,我将删除重复项,以便只保留唯一的地址:
df = df[['Address']]
df = df.drop_duplicates()
再次查看数据框的前几行,我们只能看到address列:
图片作者提供
很好!我们现在可以开始地理编码了。
首先,我们需要用 Python 访问我们的 API 密钥。运行以下代码行来完成此操作:
gmaps_key = googlemaps.Client(key="your_API_key")
现在,让我们尝试首先进行一个地址的地理编码,并查看输出结果。
add_1 = df['Address'][0]
g = gmaps_key.geocode(add_1)
lat = g[0]["geometry"]["location"]["lat"]
long = g[0]["geometry"]["location"]["lng"]
print('Latitude: '+str(lat)+', Longitude: '+str(long))
上述代码的输出如下所示:
图片作者提供
如果你得到了上述输出,太好了!一切正常。
我们现在可以对整个数据框重复这个过程:
# geocode the entire dataframe:
def geocode(add):
g = gmaps_key.geocode(add)
lat = g[0]["geometry"]["location"]["lat"]
lng = g[0]["geometry"]["location"]["lng"]
return (lat, lng)
df['geocoded'] = df['Address'].apply(geocode)
让我们再次查看数据框的前几行,看看这是否有效:
df.head()
如果你的输出与上面的截图类似,恭喜你!你已经成功对整个数据框进行了地址地理编码。
OpenStreetMap API 完全免费,但比 Google 地图 API 更慢且准确度较低。
这个 API 无法找到数据集中的许多地址,因此这次我们将使用locality列。
在我们开始教程之前,让我们看看address列和locality列之间的区别。运行以下代码行来完成此操作:
print('Address: '+data['Address'][0]+'\n\nLocality: '+data['Locality'][0])
你的输出将如下所示:
图片作者提供
address列比locality列更详细,它提供了餐厅的确切位置,包括楼层号。这可能是地址未被 OpenStreetMap API 识别的原因,但locality却被识别了。
让我们对第一个locality进行地理编码,并查看输出结果。
运行以下代码行:
import url
import requests
data = data[['Locality']]
url = 'https://nominatim.openstreetmap.org/search/' + urllib.parse.quote(df['Locality'][0]) +'?format=json'
response = requests.get(url).json()
print('Latitude: '+response[0]['lat']+', Longitude: '+response[0]['lon'])
上述代码的输出与 Google Maps API 生成的结果非常相似:
图片作者提供
现在,让我们创建一个函数来查找整个数据框的坐标:
def geocode2(locality):
url = 'https://nominatim.openstreetmap.org/search/' + urllib.parse.quote(locality) +'?format=json'
response = requests.get(url).json()
if(len(response)!=0):
return(response[0]['lat'], response[0]['lon'])
else:
return('-1')
data['geocoded'] = data['Locality'].apply(geocode2)
很好!现在,让我们查看数据框的前几行:
data.head(15)
请注意,这个 API 无法为数据框中的许多地点生成坐标。
尽管这是 Google Maps API 的一个很好的免费替代品,但如果使用 OpenStreetMap 进行地理编码,你可能会丢失很多数据。
本教程就到这里!希望你能从中学到一些新知识,对处理地理空间数据有更好的理解。
祝你在数据科学之旅中好运,感谢你的阅读!
Natassha Selvaraj 是一位自学成才的数据科学家,热衷于写作。你可以通过LinkedIn与她联系。
原文。转载已获许可。
1. Google 网络安全证书 - 快速入门网络安全职业。
2. Google 数据分析专业证书 - 提升你的数据分析水平
3. Google IT 支持专业证书 - 支持你的组织进行 IT 支持