根据列表选择数据框值

时间:2021-04-04 18:45:38

标签: python pandas dataframe

我有一个包含 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]

我只想从这个多边形内部的数据框中选择数据,或者从多边形外部的数据框中删除数据

3 个答案:

答案 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