Как эффективно сделать точку в запросе полигона, используя geo pandas? - PullRequest
3 голосов
/ 09 апреля 2020

У меня есть шейп-файл со всеми округами США, и я делаю кучу запросов в точке широты и долготы, а затем нахожу, в каком округе находится точка. Прямо сейчас я просто перебираю все графства и делать pnt.within (графство). Это не очень эффективно. Есть ли лучший способ сделать это?

1 Ответ

4 голосов
/ 16 апреля 2020

Ваша ситуация выглядит как типичный случай, когда spatial joins полезны. Идея пространственных объединений заключается в объединении данных с использованием географических c координат вместо использования атрибутов.

Три возможности в geopandas:

  • intersects
  • within
  • contains

Похоже, вы хотите within, что возможно с использованием следующего синтаксиса:

geopandas.sjoin(points, polygons, how="inner", op='within')

Примечание. Для выполнения таких операций необходимо установить rtree. Если вам нужно установить эту зависимость, используйте pip или conda для ее установки

Пример

В качестве примера, давайте построим европейские города. Два примера наборов данных:

import geopandas
import matplotlib.pyplot as plt

world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
cities = geopandas.read_file(geopandas.datasets.get_path('naturalearth_cities'))
countries = world[world['continent'] == "Europe"].rename(columns={'name':'country'})

countries.head(2)
    pop_est     continent   country     iso_a3  gdp_md_est  geometry
18  142257519   Europe  Russia  RUS     3745000.0   MULTIPOLYGON (((178.725 71.099, 180.000 71.516...
21  5320045     Europe  Norway  -99     364700.0    MULTIPOLYGON (((15.143 79.674, 15.523 80.016, ...

cities.head(2)
    name    geometry
0   Vatican City    POINT (12.45339 41.90328)
1   San Marino  POINT (12.44177 43.93610)

cities - это набор данных по всему миру, а countries - это набор данных по всей Европе.

Оба набора данных должны находиться в одной проекционной системе. Если нет, используйте .to_crs перед объединением.

data_merged = geopandas.sjoin(cities, countries, how="inner", op='within')

Наконец, чтобы увидеть результат, давайте создадим карту

f, ax = plt.subplots(1, figsize=(20,10))
data_merged.plot(axes=ax)
countries.plot(axes=ax, alpha=0.25, linewidth=0.1)
plt.show()

enter image description here

и базовый набор данных объединится вместе информация, которая нам нужна

data_merged.head(5)

    name    geometry    index_right     pop_est     continent   country     iso_a3  gdp_md_est
0   Vatican City    POINT (12.45339 41.90328)   141     62137802    Europe  Italy   ITA     2221000.0
1   San Marino  POINT (12.44177 43.93610)   141     62137802    Europe  Italy   ITA     2221000.0
192     Rome    POINT (12.48131 41.89790)   141     62137802    Europe  Italy   ITA     2221000.0
2   Vaduz   POINT (9.51667 47.13372)    114     8754413     Europe  Austria     AUT     416600.0
184     Vienna  POINT (16.36469 48.20196)   114     8754413     Europe  Austria     AUT     416600.0

Здесь я использовал inner метод соединения, но это параметр, который вы можете изменить, если, например, вы хотите сохранить все точки, в том числе не в пределах многоугольника.

...