Сегментируйте панду DataFrame, содержащую широту / долготу по заданному геойсону - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть DataFrame, содержащий столбцы lat и lng.У меня также есть FeatureCollection геойсон, который содержит многоугольник.Учитывая этот многоугольник, как я могу сегментировать мой df и выбирать только те строки, которые находятся внутри данного многоугольника эффективным способом?Я хочу избежать зацикливания на df и проверки каждого элемента вручную.

d = {'lat' : [0,0.1,-0.1,0.4],
    'lng' : [50,50.1,49.6,49.5]}


df = pd.DataFrame(d)

Это коллекция объектов, которая отображает 1 многоугольник и 4 точки.Как видите, только последний пункт находится снаружи.

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              0,
              49
            ],
            [
              0.6,
              50
            ],
            [
              0.1,
              52
            ],
            [
              -1,
              51
            ],
            [
              0,
              49
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          0,
          50
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          0.1,
          50.1
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          -0.1,
          49.6
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          0.4,
          49.5
        ]
      }
    }
  ]
}

эта карта отображает многоугольник и точки.

Редактировать: Ниже приведен код, который у меня есть на данный момент, но, как вы можете ожидать, он очень медленный.

from shapely.geometry import shape, Point
# check each polygon to see if it contains the point
for feature in feature_collection['features']:
    polygon = shape(feature['geometry'])
    for index, row in dfr.iterrows():
        point = Point(row.location_lng, row.location_lat)
        if polygon.contains(point):
            print('Found containing polygon:', feature)

, где dfr - мой DataFrame, содержащий location_lat и location_lng.feature_collection является коллекцией объектов geojson, в которой есть только многоугольники (обратите внимание, что приведенный выше пример geojson предназначен только для объяснения вопроса, он имеет только 1 многоугольник и имеет несколько точек для иллюстрации вопроса).

1 Ответ

0 голосов
/ 29 ноября 2018

Предполагая, что у вас есть фрейм данных dfr, например:

   location_lat  location_lng
0           0.0          50.0
1           0.1          50.1
2          -0.1          49.6
3           0.4          49.5

и feature_collection, содержащие такие полигоны, как:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [[[0,49],[0.6,50],[0.1,52],[-1,51],[0,49]]]
      }
    },
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [[[0,50],[0.6,50],[0.1,52],[-1,51],[0,50]]]
      }
    }]
}

Я изменяю 49 на 50 во втором многоугольникечтобы удалить другие точки в нем.

Вы можете сначала создать столбец с точками в dfr:

#using Point from shapely and apply
from shapely.geometry import Point
dfr['point'] = dfr[['location_lat', 'location_lng']].apply(Point,axis=1)

#or use MultiPoint faster
from shapely.geometry import MultiPoint
dfr['point'] = list(MultiPoint(dfr[['location_lat', 'location_lng']].values))

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

Теперь вы можете создать столбец для каждого многоугольника в feature_collection, содержащий, если точка принадлежит объекту, я думаю, зацикливая на них:

from shapely.geometry import shape
for i, feature in enumerate(feature_collection['features']):
    dfr['feature_{}'.format(i)] = list(map(shape(feature['geometry']).contains,dfr['point']))

тогда dfr выглядит следующим образом:

   location_lat  location_lng              point  feature_0  feature_1
0           0.0          50.0       POINT (0 50)       True      False
1           0.1          50.1   POINT (0.1 50.1)       True       True
2          -0.1          49.6  POINT (-0.1 49.6)       True      False
3           0.4          49.5   POINT (0.4 49.5)      False      False

Чтобы выбрать точку, принадлежащую объекту, выполните:

print (dfr.loc[dfr['feature_1'],['location_lat', 'location_lng']])
   location_lat  location_lng
1           0.1          50.1
...