从坐标 and/or 邮政编码中获取 NUTS2 区域
Fetching NUTS2 region from geocoordinates and/or postalcode
我有一个包含地理坐标和邮政编码等数据的 df。
lat | lon | postcode
54.3077 | 12.7 | 18314
51.898 | 9.26 | 32676
我需要一个包含 NUTS2 区域的新列,因此在这种情况下,生成的 df 应该如下所示:
lat | lon | postcode | NUTS_ID
54.3077 | 12.7 | 18314 | DE80
51.898 | 9.26 | 32676 | DEA4
我找到了这个包:https://github.com/vis4/pyshpgeocode,我设法 运行。我的第一个方法是以下两个函数:
def get_gc(nuts='geoc\shapes\nuts2\nuts2.shp'):
"""
nuts -> path to nuts file
"""
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
return gc
def add_nuts_to_df(df):
"""
df must have lon/lat geocoodinates in it
This function will add a column ['NUTS_ID'] with the corresponding
NUTS region
"""
start_time = time.time()
for idx, row in df.iterrows():
df.loc[idx, 'NUTS_ID'] = get_gc().geocode(row.lat,
row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
print('Done with index {}\nTime since start: {}s'.format(idx,
round(time.time() - start_time, 0 )))
return df
这确实有效!但是,一个条目需要大约 0.6 秒,而我的一些 df 有超过一百万个条目。由于我的原始数据框通常包含邮政编码,我正在考虑使用 groupby / apply / transform?
的组合来聚合它们
或者还有其他(更有效)的方法吗?
非常感谢任何帮助,并期待收到回复。
如果我正确理解了您的代码,那么您正在为同一输入文件中的每个请求重新创建 gc
对象。我不明白为什么。
因此,一种可能是执行以下操作:
def add_nuts_to_df(df):
"""
df must have lon/lat geocoodinates in it
This function will add a column ['NUTS_ID'] with the corresponding
NUTS region
"""
nuts='geoc\shapes\nuts2\nuts2.shp'
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
start_time = time.time()
for idx, row in df.iterrows():
df.loc[idx, 'NUTS_ID'] = gc.geocode(row.lat,
row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
print('Done with index {}\nTime since start: {}s'.format(idx,
round(time.time() - start_time, 0 )))
return df
如果您尝试使用 df.apply()
方法并在其中的函数中传递您的地理编码逻辑,也许它会进一步加快该过程。
类似于:
nuts='geoc\shapes\nuts2\nuts2.shp'
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
def get_nuts_id(row):
return gc.geocode(row.lat, row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
df["NUTS_ID"] = df.apply(get_nuts_id,axis=1)
虽然我没有尝试过,但请注意错别字。
我有一个包含地理坐标和邮政编码等数据的 df。
lat | lon | postcode
54.3077 | 12.7 | 18314
51.898 | 9.26 | 32676
我需要一个包含 NUTS2 区域的新列,因此在这种情况下,生成的 df 应该如下所示:
lat | lon | postcode | NUTS_ID
54.3077 | 12.7 | 18314 | DE80
51.898 | 9.26 | 32676 | DEA4
我找到了这个包:https://github.com/vis4/pyshpgeocode,我设法 运行。我的第一个方法是以下两个函数:
def get_gc(nuts='geoc\shapes\nuts2\nuts2.shp'):
"""
nuts -> path to nuts file
"""
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
return gc
def add_nuts_to_df(df):
"""
df must have lon/lat geocoodinates in it
This function will add a column ['NUTS_ID'] with the corresponding
NUTS region
"""
start_time = time.time()
for idx, row in df.iterrows():
df.loc[idx, 'NUTS_ID'] = get_gc().geocode(row.lat,
row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
print('Done with index {}\nTime since start: {}s'.format(idx,
round(time.time() - start_time, 0 )))
return df
这确实有效!但是,一个条目需要大约 0.6 秒,而我的一些 df 有超过一百万个条目。由于我的原始数据框通常包含邮政编码,我正在考虑使用 groupby / apply / transform?
的组合来聚合它们或者还有其他(更有效)的方法吗?
非常感谢任何帮助,并期待收到回复。
如果我正确理解了您的代码,那么您正在为同一输入文件中的每个请求重新创建 gc
对象。我不明白为什么。
因此,一种可能是执行以下操作:
def add_nuts_to_df(df):
"""
df must have lon/lat geocoodinates in it
This function will add a column ['NUTS_ID'] with the corresponding
NUTS region
"""
nuts='geoc\shapes\nuts2\nuts2.shp'
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
start_time = time.time()
for idx, row in df.iterrows():
df.loc[idx, 'NUTS_ID'] = gc.geocode(row.lat,
row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
print('Done with index {}\nTime since start: {}s'.format(idx,
round(time.time() - start_time, 0 )))
return df
如果您尝试使用 df.apply()
方法并在其中的函数中传递您的地理编码逻辑,也许它会进一步加快该过程。
类似于:
nuts='geoc\shapes\nuts2\nuts2.shp'
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
def get_nuts_id(row):
return gc.geocode(row.lat, row.lon,
filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
df["NUTS_ID"] = df.apply(get_nuts_id,axis=1)
虽然我没有尝试过,但请注意错别字。