3

I want to filter GeoPandas GeoDataFrame rows by a list containing 4 'matches';
list_of_names = ['BE36_1000_1349', 'BE36_1000_1350', 'BE36_1000_1449', 'BE36_1000_1450'].

I want to return four complete rows that have the index_tile column matching the 4 elements in the above list.

print (topo50_df.filter(like=list_of_names))
--------------------------------------------
TypeError: 'in <string>' requires string as left operand, not list

print (topo50_df.query(str(list_of_names))) 
--------------------------------------------
KeyError(f"None of [{key}] are in the [{axis_name}]") KeyError: "None of 
[Index(['BE36_1000_1349', 'BE36_1000_1350', 'BE36_1000_1449', 
'BE36_1000_1450'], dtype='object')] are in the [index]"
import geopandas as gpd
from shapely.geometry import Polygon

imagery_bb_polygon_df = gpd.GeoDataFrame(index=[0], crs=("epsg:2193"), geometry=[Polygon(list_of_points)])
topo50_df = gpd.read_file(topo50_geometry_file)

intersection_matches = topo50_df.overlay(imagery_bb_polygon_df, how='intersection', keep_geom_type=False)
list_of_names = list(intersection_matches.loc[1:4, 'index_tile'])

My GeoDataFrame named topo50_ref looks like this:

                index_tile sheet_code  scale  tile                                           geometry
210648  BE36_1000_1349       BE36   1000  1349  POLYGON ((1875520.000 5792640.000, 1875040.000...
210649  BE36_1000_1350       BE36   1000  1350  POLYGON ((1876000.000 5792640.000, 1875520.000...
210698  BE36_1000_1449       BE36   1000  1449  POLYGON ((1875520.000 5791920.000, 1875040.000...
210699  BE36_1000_1450       BE36   1000  1450  POLYGON ((1876000.000 5791920.000, 1875520.000...
<class 'geopandas.geodataframe.GeoDataFrame'>

2 Answers 2

4

Use isin, see Use a list of values to select rows from a Pandas dataframe:

import geopandas as gpd

list_of_names = ['2262', '2361', '2161', '2039', '2132']

df = gpd.read_file(r"C:\GIS\data\testdata\ak_riks_lines.shp")
#df.shape
#Out: (294, 16)

fieldname = 'KOM_KOD'

df2 = df[df[fieldname].isin(list_of_names)]
#df2.shape
#(5, 16)
3

Another approach utilizes the .query(), that was also mentioned in the Use a list of values to select rows from a Pandas dataframe.

import geopandas as gpd

list_of_names = ['Type 1', 'Type 3']

_layer = "C:/Documents/Python Scripts/geopandas/layer.shp"

layer = gpd.read_file(_layer)
print(layer)

   fid    Type                                           geometry
0  1.0  Type 1  POLYGON ((413827.594 5289710.674, 610390.807 5...
1  2.0  Type 2  POLYGON ((1118850.852 5483173.520, 1415245.854...
2  3.0  Type 3  POLYGON ((413827.594 5289710.674, 613697.864 4...

layer_filtered = layer.query('Type in @list_of_names')
print(layer_filtered)

   fid    Type                                           geometry
0  1.0  Type 1  POLYGON ((413827.594 5289710.674, 610390.807 5...
2  3.0  Type 3  POLYGON ((413827.594 5289710.674, 613697.864 4...

As mentioned in Indexing and selecting data | Performance of query():

DataFrame.query() using numexpr is slightly faster than Python for large frames.


Why are you getting that error? Because you are missing 'index_tile in ..., the vital component for the .query().

If I do the same i.e. layer.query(str('@list_of_values')) I will get exactly your error:

    raise KeyError(f"None of [{key}] are in the [{axis_name}]")
KeyError: "None of [Index(['Type 1', 'Type 3'], dtype='object')] are in the [index]"

So, you need to apply a tiny change:

layer_filtered = layer.query('index_tile in @list_of_names')
print(layer_filtered)

References:

2
  • This did not work for me, I cannot 'Type in @list_of_names' as I want to automate everything, I typed in str(list_of_names) e.g. layer_filtered = layer.query(str(list_of_names) and got this error raise KeyError(f"None of [{key}] are in the [{axis_name}]") KeyError: "None of [Index(['BE36_1000_1349', 'BE36_1000_1350', 'BE36_1000_1449', 'BE36_1000_1450'], dtype='object')] are in the [index]"
    – Rose
    Commented Nov 18, 2021 at 8:54
  • 1
    Probably because "Type" does not exist in your GeoDataFrame, use layer_filtered = layer.query('index_tile in @list_of_names') instead. Can you please edit your question with this error as well as the code that you are using.
    – Taras
    Commented Nov 18, 2021 at 8:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.