从坐标 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)

虽然我没有尝试过,但请注意错别字。