I have a dataframe of health survey data which is geotagged, called
momdata. I have converted the dataframe to a GeoPandas dataframe, and used the geotags as the geometry column within the dataframe, for example:
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)
I want to filter the dataframe so that only points in the UK are returned. I have the UK coordinates in a separate Geoseries, called uk_geom, which I simply took from the GeoPandas built-in world map:
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']
This returns uk_geom as a GeoPandas GeoSeries:
type(uk_geom) # geopandas.geoseries.GeoSeries
I simply want to filter
momdata for all points within momdata.geometry that fall within uk_geom, returning a dataframe of only UK-based survey observations. This should be simple.
uk_momdata = momdata[momdata.geometry.within(uk_geom)]
but this returns an empty dataframe, when I know that some of the survey observations for sure are in the UK.
p1 = momdata.geometry.loc p2 = momdata.geometry.loc print(uk_geom.contains(p1)) # returns TRUE print(uk_geom.contains(p2)) # returns TRUE
I tried this the other way round, checking which momdata points are contained within uk_geom:
uk_geom.contains(momdata.geometry).value_counts() #2040 false points
Also when I test the 'within' function on a point that I know is within
momdata, I get an error:
print(point8.within(uk_geom)) # AttributeError: 'GeoSeries' object has no attribute '_geom'
I have assigned the correct co-ordinate reference system:
assert uk_geom.crs == momdata.crs # no problem
I also tried a basic 'apply' function using a predicate, but this returns an error:
momdata[momdata.geometry.apply(lambda p: uk_geom.contains(p))] # Null geometry supports no operations
I also tried a spatial join, but then I get the error that one of the join columns is not a DataFrame, as of course it's trying to join on the geometry column:
from geopandas.tools import sjoin join_left_df = sjoin(momdata, uk_geom, how="left") join_left_df
How do I solve this?
I can't seem to make it work.
uk_momdata = momdata[momdata.geometry.within(uk_geom)]returned an empty dataframe is because
uk_geomwas not a single Polygon, but a GeoSeries of that single polygon, and if you then do a
withinoperation, it will do the operation element-wise but aligned on the index. In your case you need to ensure
uk_geomis a single Polygon, which is what is done in the answer of @LucieCBurgess