我有一个包含 1259 个数据的坐标和高程的数据框。
df_elevation
Longitud Latitud Elevación
0 -5.879263 42.579535 937
1 -5.879303 42.579535 937
2 -5.879342 42.579535 937
3 -5.879382 42.579535 937
4 -5.879422 42.579535 937
... ... ... ...
1255 -5.880498 42.582213 933
1256 -5.880538 42.582213 933
1257 -5.880578 42.582213 933
1258 -5.880618 42.582213 933
1259 -5.880657 42.582213 933
1260 rows × 3 columns
我有一个由坐标多边形组成的列表。
lat_list = [42.582213356031694, 42.57966169458114, 42.57945629314298, 42.582142258520136, 42.582213356031694]
lon_list = [-5.880088806152344, -5.880657434463501, -5.879863500595092, -5.879262685775757, -5.880088806152344]
我只想从这个多边形内部的数据框中选择数据,或者从多边形外部的数据框中删除数据
答案 0 :(得分:2)
您可以使用 shapely
创建点和多边形,然后使用 within
检查点是否在多边形中。在这个例子中,我通过一个函数运行它,该函数创建一个额外的列,指示点是否在多边形中。然后你可以过滤df。请注意,我添加了一些示例数据,因为您的示例 df 中的所有点实际上都不在多边形中:
from shapely.geometry import Point, Polygon
import pandas as pd
data = [ { "ID": 0, "Longitud": -5.879263, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 1, "Longitud": -5.879303, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 2, "Longitud": -5.879342, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 3, "Longitud": -5.879382, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 4, "Longitud": -5.879422, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 1255, "Longitud": -5.880498, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1256, "Longitud": -5.880538, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1257, "Longitud": -5.880578, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1258, "Longitud": -5.880618, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1259, "Longitud": -5.880657, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1260, "Longitud": -5.879323515030888, "Latitud": 42.58192907018969, "Elevación": 933 }, { "ID": 1261, "Longitud": -5.879799662054768, "Latitud": 42.58143025825665, "Elevación": 933 }, { "ID": 1262, "Longitud": -5.880003215470649, "Latitud": 42.58117728748368, "Elevación": 933 } ]
df = pd.DataFrame(data)
df = df.set_index('ID')
lat_list = [42.582213356031694, 42.57966169458114, 42.57945629314298, 42.582142258520136, 42.582213356031694]
lon_list = [-5.880088806152344, -5.880657434463501, -5.879863500595092, -5.879262685775757, -5.880088806152344]
polygon = Polygon(zip(lon_list, lat_list))
def check_polygon(row):
return Point(row['Longitud'], row['Latitud']).within(polygon)
df['inpolygon'] = df.apply(check_polygon, axis=1)
df = df[df['inpolygon'] == True]
输出:
ID | 纵向 | 纬度 | 电梯 | inpolygon |
---|---|---|---|---|
1260 | -5.87932 | 42.5819 | 933 | 真 |
1261 | -5.8798 | 42.5814 | 933 | 真 |
1262 | -5.88 | 42.5812 | 933 | 真 |
答案 1 :(得分:1)
如果您有一个大型数据集,我建议使用空间索引,因为它会大大减少处理时间。 Geopandas 对 R 树空间索引进行了巧妙的实现,GeoffBoeing 对此进行了解释very nicely
这是一个扩展@RJ 答案的示例。首先,我们将再次构建 df。
enqueue=True
接下来,我们将使用 gpd 的 points_from_xy() 创建一个地理数据框。
from shapely.geometry import Point, Polygon
import pandas as pd
data = [ { "ID": 0, "Longitud": -5.879263, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 1, "Longitud": -5.879303, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 2, "Longitud": -5.879342, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 3, "Longitud": -5.879382, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 4, "Longitud": -5.879422, "Latitud": 42.579535, "Elevación": 937 }, { "ID": 1255, "Longitud": -5.880498, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1256, "Longitud": -5.880538, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1257, "Longitud": -5.880578, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1258, "Longitud": -5.880618, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1259, "Longitud": -5.880657, "Latitud": 42.582213, "Elevación": 933 }, { "ID": 1260, "Longitud": -5.879323515030888, "Latitud": 42.58192907018969, "Elevación": 933 }, { "ID": 1261, "Longitud": -5.879799662054768, "Latitud": 42.58143025825665, "Elevación": 933 }, { "ID": 1262, "Longitud": -5.880003215470649, "Latitud": 42.58117728748368, "Elevación": 933 } ]
df = pd.DataFrame(data)
df = df.set_index('ID')
lat_list = [42.582213356031694, 42.57966169458114, 42.57945629314298, 42.582142258520136, 42.582213356031694]
lon_list = [-5.880088806152344, -5.880657434463501, -5.879863500595092, -5.879262685775757, -5.880088806152344]
polygon = Polygon(zip(lon_list, lat_list))
为了展示空间索引所节省的时间,我们可以以虚拟方式扩展我们的地理数据框。我们创建了一个 gdf 列表,然后我们创建了 pd.concat() 这样我们就有了一个更大的地理数据框。这给了我们 130,000 行而不是 13 行。
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df['Longitud'], df['Latitud']))
最后,我们创建空间索引,然后使用它返回多边形内包含点的行。注意在 Jupyter 中使用 timeit%% 魔法命令会导致变量保存失败。
gdf_list = [gdf] * 10000
gdf_cat = pd.concat(gdf_list)
在 Jupyter 中使用 timit magic 命令,我们可以看到比使用空间索引的 apply 方法快 3 倍。
%%timeit
spatial_index = gdf_cat.sindex
possible_matches_index = list(spatial_index.intersection(polygon.bounds))
possible_matches = gdf_cat.iloc[possible_matches_index]
precise_matches = possible_matches[possible_matches.intersects(polygon)]
这是与 apply() 一起使用的 check_polygon 函数和原始 df 的扩展。
1.95 s ± 48.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
展开后,我们展示了没有空间索引的速度。
def check_polygon(row):
return Point(row['Longitud'], row['Latitud']).within(polygon)
df_list = [df] * 10000
df_cat = pd.concat(df_list)
看到它慢了很多。
%%timeit
df_cat['inpolygon'] = df_cat.apply(check_polygon, axis=1)
df_cat_slice = df_cat[df_cat['inpolygon'] == True]
答案 2 :(得分:0)
我将首先使用 shapely.geometry.Polygon 从坐标创建一个匀称的多边形,我还将所有坐标转换为 shapely.geometry.Point 对象并使用 contains() 方法查看哪些点在多边形内.然后您只需索引其余部分。你也可以使用 geopandas 来做到这一点,但它是可选的
您可以看到 contains() 方法的工作原理 here