Pandas加速reverse_geocoder在列与字符串和坐标

zf2sa74q  于 2024-01-04  发布在  其他
关注(0)|答案(1)|浏览(130)

我有一个像这样的有两列的框架:

  1. country_code geo_coords
  2. GB nan
  3. nan [13.43, 52.48]
  4. TR nan
  5. ...

字符串
我想使用geo_coords列中的信息在country_code中填充nan值。
为了从坐标中提取国家代码,我使用了reverse_geocoder模块。
这是我的代码:

  1. def from_coords_to_code(coords):
  2. """Find the country code of coordinates.
  3. Args:
  4. coords: coordinates of the point in [lon, lat] format
  5. """
  6. return rg.search(coords[::-1])[0]["cc"]
  7. sub_df["country_code"].fillna(sub_df["geo_coords"], inplace=True)
  8. sub_df["country_code"] = sub_df["country_code"].apply(
  9. lambda x: from_coords_to_code(x) if isinstance(x, list) else x
  10. )


由于我有成千上万的行,这段代码非常慢。
在另一个question之后,我试图在删除nan值后对整个geo_coords列应用反向地理编码:

  1. geo_coords = df["geo_coords"].loc[df["geo_coords"].notna()]
  2. geo_coords_tuple = tuple(geo_coords.apply(lambda x: tuple(x[::-1])))
  3. cc_new = rg.search(geo_coords_tuple, mode=2)
  4. country_code = [i["cc"] for i in cc_new]
  5. for i, j in enumerate(geo_coords.index):
  6. df["country_code"].iloc[j] = country_code[i]


这样会更快,但它给了我一个警告:

  1. A value is trying to be set on a copy of a slice from a DataFrame
  2. See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  3. sub_df["country_code"].iloc[j] = country_code[i]


我想避免这种情况,我不确定这是一个最佳解决方案。
有什么建议可以让整个代码更高效吗?
我很高兴从“reverse_geocoder”转移到任何其他模块。
重要:geo_coords中的坐标是geoJSON格式的,即[lon,lat],这就是我将它们反转的原因。

kmbjn2e3

kmbjn2e31#

函数rg.search()非常慢,而且已经使用了多个核心。我能够加快搜索速度,以便向任务添加额外的工作人员,使用ProcessPoolExecutor,例如:

  1. from concurrent.futures import ProcessPoolExecutor as Pool
  2. import pandas as pd
  3. import reverse_geocoder as rg
  4. from tqdm import tqdm
  5. def process_coord(tpl):
  6. idx, (a, b) = tpl
  7. return idx, rg.search((b, a))[0]["cc"]
  8. if __name__ == "__main__":
  9. # sample dataframe:
  10. df = pd.DataFrame(
  11. {
  12. "country_code": ["GB", None, "TR"] * 10_000,
  13. "geo_coords": [None, [13.43, 52.48], None] * 10_000,
  14. }
  15. )
  16. with Pool(max_workers=2) as pool:
  17. mask = df["country_code"].isna()
  18. for i, result in tqdm(
  19. pool.map(process_coord, zip(df.index[mask], df.loc[mask, "geo_coords"])),
  20. total=mask.sum(),
  21. ):
  22. df.loc[i, "country_code"] = result
  23. print(df)

字符串
在我的电脑(AMD 5700x)上,这是每秒17次搜索。

  1. 5%|████████▌ | 507/10000 [00:29<09:12, 17.19it/s]

展开查看全部

相关问题