如何使此功能更有效/并行运行?

时间:2017-11-18 21:10:03

标签: python performance pandas dataframe arcgis

我正在尝试使用地理编码程序包将33000个zipcodes转换为坐标。我希望有一种方法来并行化这种方法,因为它消耗了相当多的资源。

from geopy.geocoders import ArcGIS
import pandas as pd
import time
geolocator = ArcGIS()
df1 = pd.DataFrame(0.0, index=list(range(0,len(df))), columns=list(['lat','lon']))
df = pd.concat([df,df1], axis=1)
for index in range(0,len(df)):
      row = df['zipcode'].loc[index]
      print index
#      time.sleep(1) 
#    I put this function in just in case it would give me a timeout error. 
      myzip = geolocator.geocode(row)
      try: 
        df['lat'].loc[index] = myzip.latitude
        df['lon'].loc[index] = myzip.longitude
      except: 
        continue 

2 个答案:

答案 0 :(得分:2)

geopy.geocoders.ArcGIS.geocode查询网络服务器。单独发送33,000个查询可能会让您被禁止IP,因此我不建议并行发送它们。

您正在查找美国几乎所有的邮政编码。美国人口普查局有一个1MB的CSV文件,其中包含33,144个邮政编码的这些信息:https://www.census.gov/geo/maps-data/data/gazetteer2017.html

您可以在几分之一秒内完成所有操作:

zip_df = pd.read_csv('2017_Gaz_zcta_national.zip', sep='\t')
zip_df.rename(columns=str.strip, inplace=True)

需要注意的一点是,Pandas没有正确解析最后一列的名称,并且包含大量尾随空格。您必须在使用前删除列名称。

答案 1 :(得分:-1)

使用multiprocessing.Pool

,这是一种方法
from multiprocessing import Pool

def get_longlat(x):
    index, row = x
    print index
    time.sleep(1)
    myzip = geolocator.geocode(row['zipcode'])
    try:
        return myzip.latitude, myzip.longitude
    except:
        return None, None

p = Pool()
df[['lat', 'long']] = p.map(get_longlat, df.iterrows())

更一般地说,使用DataFrame.iterrows(每个迭代的项目是一个索引,行元组)可能比上面使用的基于索引的方法更有效

编辑:在阅读完其他答案后,您应该了解速率限制;但是,您可以在Pool中使用固定数量的进程以及time.sleep延迟来缓解这种情况。