8 votos

Filtrar un marco de datos GeoPandas por puntos dentro de un país específico

Tengo un marco de datos de encuestas sanitarias con geoetiquetas, llamado momdata . He convertido el marco de datos en un marco de datos GeoPandas y he utilizado las geoetiquetas como columna de geometría dentro del marco de datos, por ejemplo:

momdata['geometry']

0        POINT (-0.0893 51.4735)
1       POINT (-0.0894 51.4732)
2         POINT (-0.0898 51.4717)
3        POINT (-0.0907 51.4727)
4       POINT (-0.0901 51.4723)
5       POINT (-0.0816 51.4742)

Quiero filtrar el marco de datos para que sólo aparezcan los puntos del Reino Unido. Tengo las coordenadas del Reino Unido en una Geoserie separada, llamada uk_geom, que simplemente tomé del mapa mundial incorporado en GeoPandas:

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
uk_index = world[world.name == "United Kingdom"].index
uk_geom = world.loc[uk_index, 'geometry']

Devuelve uk_geom como GeoSeries de GeoPandas:

type(uk_geom) # geopandas.geoseries.GeoSeries

Simplemente quiero filtrar momdata para todos los puntos de momdata.geometry que caen dentro de uk_geom, devolviendo un marco de datos de sólo observaciones de encuestas basadas en el Reino Unido. Esto debería ser sencillo.

Lo intenté:

uk_momdata = momdata[momdata.geometry.within(uk_geom)]

pero esto devuelve un marco de datos vacío, cuando sé que algunas de las observaciones de la encuesta se encuentran con seguridad en el Reino Unido.

Por ejemplo:

p1 = momdata.geometry.loc[0]
p2 = momdata.geometry.loc[1]

print(uk_geom.contains(p1)) # returns TRUE
print(uk_geom.contains(p2)) # returns TRUE

Lo he intentado al revés, comprobando qué puntos momdata contiene uk_geom:

uk_geom.contains(momdata.geometry).value_counts() #2040 false points

También cuando pruebo la función 'within' en un punto que sé que está dentro de momdata Obtengo un error:

print(point8.within(uk_geom)) # AttributeError: 'GeoSeries' object has no attribute '_geom' 

He asignado el sistema de referencia de coordenadas correcto:

assert uk_geom.crs == momdata.crs # no problem

También he intentado una función básica "aplicar" utilizando un predicado, pero esto devuelve un error:

momdata[momdata.geometry.apply(lambda p: uk_geom.contains(p))] # Null geometry supports no operations

También he intentado una unión espacial, pero entonces me sale el error de que una de las columnas de la unión no es un DataFrame, ya que por supuesto está intentando unirse en la columna de geometría:

from geopandas.tools import sjoin
join_left_df = sjoin(momdata, uk_geom, how="left")
join_left_df

¿Cómo lo resuelvo?

No consigo que funcione.

7voto

GreyCat Puntos 146

¿Has visto Uniones espaciales más eficientes en Python sin QGIS, ArcGIS, PostGIS, etc. y otras respuestas sobre GIS SE ?

Simplemente

import geopandas as gpd
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
uk =  world[world.name == "United Kingdom"]
type(uk)
geopandas.geodataframe.GeoDataFrame

Así que uk es un GeoDataFrame

uk.head()
     pop_est     continent  name           iso_a3  gdp_md_est        geometry  
57  62262000.0    Europe   United Kingdom    GBR   1977704.0   (POLYGON ((-5.661948614921897 54.5546031764838...  

El shapefile de puntos:

points = gpd.read_file('uk_points.shp') 
points.head()
   FID                              geometry
0  0.0               POINT (-0.0893 51.4735)
1  1.0               POINT (-0.0894 51.4732) 
2  2.0               POINT (-0.0898 51.4717)
3  3.0               POINT (-0.0907 51.4727)
4  4.0               POINT (-0.0901 51.4723)

Y ahora

from geopandas.tools import sjoin
pointInPolys = sjoin(points, uk, how='left')
pointInPolys.head()

 FID                              geometry  index_right     pop_est    continent            name iso_a3  gdp_md_est  
 0  0.0               POINT (-0.0893 51.4735)            0  62262000.0    Europe  United Kingdom    GBR   1977704.0  
 1  1.0               POINT (-0.0894 51.4732)            0  62262000.0    Europe  United Kingdom    GBR   1977704.0  
 2  2.0               POINT (-0.0898 51.4717)            0  62262000.0    Europe  United Kingdom    GBR   1977704.0  
 3  3.0               POINT (-0.0907 51.4727)            0  62262000.0    Europe  United Kingdom    GBR   1977704.0   
 4  4.0               POINT (-0.0901 51.4723)            0  62262000.0    Europe  United Kingdom    GBR   1977704.0

6voto

Brookesy Puntos 299
uk = world.ix[world['name']=='United Kingdom']
uk_mask = momdata.within(uk.loc[0, 'geometry'])
uk_momdata = momdata.loc[uk_mask]
uk_momdata

Tomado del siguiente tutorial: https://automating-gis-processes.github.io/2017/lessons/L3/point-in-polygon.html

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X