【问题标题】:How to get city, state, and country from a list of latitude and longitude coordinates?如何从经纬度坐标列表中获取城市、州和国家?
【发布时间】:2021-11-23 07:13:28
【问题描述】:

我有一个 500,000 个纬度和经度坐标列表,如下所示:

Latitude   Longitude  
42.022506  -88.168156  
41.877445  -87.723846  
29.986801  -90.166314  

我希望使用 python 来获取新列中每个坐标的城市、州和国家,如下所示:

Latitude   Longitude   City        State   Country
42.022506  -88.168156  Streamwood  IL      United States
41.877445  -87.723846  Chicago     IL      United States
29.986801  -90.166314  Metairie    LA      United States

有了这么大的数据集,如何在 python 中实现呢?我听说过 Google 的 API、Nominatim 的 API 和 Geopy 包。

如何将所有行都运行到此代码中?现在我必须在最后一行手动输入纬度和经度。

import csv 
import pandas as pd
import numpy as np
import math
from geopy.geocoders import Nominatim

input_file = "Lat-Log.csv" # file contains ID, Latitude, Longitude
output_file = "output.csv"
df = pd.read_csv(input_file) 

geolocator = Nominatim(user_agent="geoapiExercises")
def city_state_country(coord):
    location = geolocator.reverse(coord, exactly_one=True)
    address = location.raw['address']
    city = address.get('city', '')
    state = address.get('state', '')
    country = address.get('country', '')
    return city, state, country
print(city_state_country("47.470706, -99.704723"))

输出给了我('Bowdon'、'North Dakota'、'USA')。我正在寻找用我的列(纬度和经度)替换坐标以遍历我的列表。如何将我的列输入到代码中以运行整个文档?

【问题讨论】:

  • 有什么东西阻止你自己做这方面的研究吗?通常,只是询问如何做某事而没有显示代码或尝试的 StackOverflow 问题往往会被否决和关闭。我认为需要展示您的更多研究/努力。否则这基本上是一个“我想要一些代码,给我”的帖子。请参阅:How much research effort is expected of Stack Overflow users? 编辑:好的,看起来您确实提供了一些代码,但请说明您在列中遇到的问题。
  • 看起来您的代码完全符合您的要求。您希望输出是什么?与其谈论“替换列”或其他与代码相关的细节,谈论输出通常更具建设性。
  • 如果您不想预先对坐标进行排序以消除重复,至少缓存检索到的值,这样您就不会使用相同的坐标多次调用您的 api。
  • 输出为我提供了该确切位置的城市、州和国家/地区。我必须手动将纬度和经度输入print(city_state_country("47.470706, -99.704723"))。我希望用我的纬度和经度列替换坐标,并为每个坐标提供城市、州和国家,并将它们放入新列中。
  • 示例代码是你自己写的吗?

标签: python pandas latitude-longitude


【解决方案1】:

您想在每一行上运行一个函数,这可以使用apply() 来完成。

有两个复杂性,即您希望 1) 为函数提供多个参数,以及 2) 获取多个结果。

这些问题解释了如何做这些事情:

以下是调整代码以执行此操作的方法:

import pandas as pd
import io
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="geoapiExercises")

s = """Latitude   Longitude  
42.022506  -88.168156  
41.877445  -87.723846  
29.986801  -90.166314"""

df = pd.read_csv(io.StringIO(s), delim_whitespace=True)

def city_state_country(row):
    coord = f"{row['Latitude']}, {row['Longitude']}"
    location = geolocator.reverse(coord, exactly_one=True)
    address = location.raw['address']
    city = address.get('city', '')
    state = address.get('state', '')
    country = address.get('country', '')
    row['city'] = city
    row['state'] = state
    row['country'] = country
    return row

df = df.apply(city_state_country, axis=1)
print(df)

(我用数据框的内联定义替换了您的 read_csv() 调用。忽略它。这对示例并不重要。我这样做是为了使示例独立。)

city_state_country() 函数在数据帧的每一行都被调用。 (axis=1 参数使 apply() 使用行而不是列运行。)该函数获取纬度和经度,并进行查询。然后,它修改该行以包含来自查询的信息。

这会得到以下结果:

    Latitude  Longitude     city      state        country
0  42.022506 -88.168156            Illinois  United States
1  41.877445 -87.723846  Chicago   Illinois  United States
2  29.986801 -90.166314           Louisiana  United States

与您的示例不同,但 Nominatim 似乎不会为您的两个坐标返回一个城市。 (它称它们为城镇,而不是城市。)

【讨论】:

  • 你为这类问题提供了一个非常好的模式。但是,需要牢记(对于这种特殊情况),如果您尝试快速连续使用 50 万次查询来访问地理定位器服务(除非已付费),它们可能会停止工作。
  • @BrutusForcus 是的。有执行hundreds of thousands of geocoding queries 的选项,这些选项与 Nominatim 兼容。如果你想使用不同的提供者,可以在构造函数中指定提供者的域,如文档here
  • 浏览整个数据框的最佳方式是什么?是否将“geoapiExercises”替换为我的电子邮件地址?
  • @Nick 我不清楚您是否应该一次遍历整个数据框。 Nominatim API guidelines 说每秒只做 1 个请求。按照这个速度,完成 50 万个请求需要五天多的时间。如果您的互联网出现故障或计算机崩溃,您将不得不从头开始重新启动。您应该想出一个解决方案,它可以执行少量请求、保存其工作并继续,以及在崩溃后恢复。
  • @Nick 我会创建一个单独的位置和位置表,并且只请求唯一的位置,这样您就不会重复请求。实际上,您可能应该过滤彼此相距数百英尺的位置,假设它们实际上在同一个城市内,因此不需要请求。然后从该查找数据库中填写您的完整数据库。
猜你喜欢
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2013-02-08
  • 1970-01-01
  • 2011-09-03
相关资源
最近更新 更多