【问题标题】:Getting Country Name from coordinates takes too Long从坐标中获取国家名称需要太长时间
【发布时间】:2021-10-13 18:50:40
【问题描述】:

我有来自 NASA 网站的数据,其中包含一堆坐标,我试图通过 geopy 每 1 小时通过这些坐标找到它们属于哪个国家。但不幸的是,获得国家名称需要相当多的时间。

如何缩短流程时间?

这是我的代码;

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

df=pd.read_csv("https://firms.modaps.eosdis.nasa.gov/data/active_fire/modis-c6.1/csv/MODIS_C6_1_Europe_24h.csv")
df.latitude=df.latitude.astype(str)
df.longitude=df.longitude.astype(str)


country_list=[]

for i in range(len(df)):
    try:
        location = geolocator.reverse(df.latitude[i]+","+df.latitude[i])
        country=location.raw["address"]["country"]
        country_list.append(country)
    except:
        country_list.append("None")
        print(i)
        continue

df_s=pd.Series(country_list)
df["Country"]=df_s
df.to_csv("map_data_R00.csv",index=False)

【问题讨论】:

  • 定义“太长”。该 CSV 在发表评论时有 846 个条目。地理定位 800 组坐标需要 一些 时间。
  • 问题是你不能将URL(str)作为第一个参数传递给read_csv。见:-pandas.pydata.org/pandas-docs/version/0.21/generated/…
  • 看起来地理编码器正在尝试解析您经过的位置的确切地址。对于您要完成的工作,这似乎是一个很大的矫枉过正。但是这个 SO question 似乎有你需要的东西。我没有测试过。 gis.stackexchange.com/questions/88011/…
  • @DarkKnight 实际上是从路径而不是 url 读取的。我粘贴了 url 以显示 ppl 数据框的样子
  • 延迟来自 CSV 的获取。如果您从 Safari 调用该 URL 并重复执行此操作,您会注意到内容发生了变化 - 即它被附加到服务器端。我已经尝试了 requests 和 urllib 模块,并精确地模拟了在 Safari 中传输的标头,并注意响应时间约为 75 秒。如果我将超时设置为 5 秒,那么我会在该时间内得到响应(显然)。但是,内容可能不完整。如果您在浏览器中检查数据,您还会注意到最后一行通常被截断/不完整

标签: python pandas dataframe


【解决方案1】:

它是“慢”的,因为正如 Nominatim Usage Policy 中所说:

没有大量使用(每秒绝对最多 1 个请求)。

所以至少需要len(df) 秒,因为我认为它们会应用节流。此外,您可能已被屏蔽:

重复发送相同查询的客户端可能被归类为故障和阻塞。

如果您想加快速度,您可以运行自己的服务实例。文档包含instructions on how to install the software and import their data

也就是说,您的代码包含一个错误:您使用了两次纬度。此外,迭代range(len(...)) 是 Python 中的代码异味。我会选择类似的东西

import pandas as pd
from geopy.geocoders import Nominatim
geolocator = Nominatim(
    user_agent="StackOverflow Question (https://stackoverflow.com/a/68727013/383793)"
)

df = pd.read_csv("https://firms.modaps.eosdis.nasa.gov/data/active_fire/modis-c6.1/csv/MODIS_C6_1_Europe_24h.csv")

df = df.head()  # just to show an example

def to_country_code(lat: float, long: float) -> str:
    "Isn't this more generic than the country name as a string in the country's language?"
    return geolocator.reverse((lat, long)).raw['address']['country_code']
    
df['country_code'] = df[['latitude', 'longitude']].apply(
    lambda x: to_country_code(*x), axis=1
)
print(df)
纬度经度亮度扫描轨迹acq_dateacq_time\ 0 44.48386 22.69465 310.45 2.20 1.44 2021-08-09 1.0 1 42.92273 18.03089 306.02 3.97 1.85 2021-08-09 1.0 2 42.91645 18.02446 307.58 3.97 1.85 2021-08-09 1.0 3 41.26550 31.42957 302.74 1.01 1.01 2021-08-09 1.0 4 42.02151 20.29289 300.76 2.87 1.62 2021-08-09 1.0 卫星信心版本bright_t31 frp daynight country_code 0 A 80.0 6.1NRT 290.21 33.94 N ro 1 A 67.0 6.1NRT 293.46 42.59 N ba 2 A 72.0 6.1NRT 293.85 49.84 N ba 3 A 51.0 6.1NRT 292.64 5.38 N tr 4 A 33.0 6.1NRT 290.08 17.58 N al

在扩大规模之前——因为火灾数据不应该改变太多——您可以尝试缓存 Nominatim 响应。

安装 requests-cache 后,这似乎可行:

requests_cache.install_cache('geopy_cache')
geolocator = Nominatim(
    user_agent="StackOverflow Question (https://stackoverflow.com/a/68727013/383793)"
)
requests_cache.uninstall_cache()

如果你——理所当然地——对猴子补丁感到怀疑。正确的做法是在 geopy bugtracker 中获取 this issue

【讨论】:

  • 感谢您的回复。我不知道“没有大量使用(每秒绝对最多 1 个请求)。”这就是我卡住的地方,我想
  • @bibakcamki 不客气。我添加了一种缓存响应的方法。请注意,您没有将请求缓存到nasa.gov。并注意 pickle 和 requests-cache 的安全问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
  • 2016-06-11
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多