I have a GeoDataFrame (gdf
) of several thousand point locations. I want to drop duplicate records from the gdf
- that is, records with the same attribute information and the same location. However, the coordinates in the geometry column have way more precision than I need for my analysis, which means that coordinates that are "functionally the same" for my purposes (e.g., the same up to the 5th decimal place) don't have identical geometries.
Sample data for reproducibility:
import pandas as pd
import geopandas as gpd
df = pd.DataFrame({'fid': [0, 1, 2, 3, 4, 5],
'location_name': ['ABC', 'ABC', 'DEF', 'DEF', 'JKL', 'JKL'],
'equipment': ['tank', 'tank', 'generator', 'generator', 'tank', 'generator']
})
coords = ['POINT (-68.85052703049803 -46.03444179295434)',
'POINT (-68.85052703049802 -46.03443956295743)',
'POINT (-68.60401999999993 -37.49876999999998)',
'POINT (-69.17996992199994 -38.91214629699994)',
'POINT (-69.29235725099994 -38.55542628499995)',
'POINT (-69.29235725099992 -38.5554262849999)']
gdf = gpd.GeoDataFrame(data=df,
geometry=gpd.GeoSeries.from_wkt(coords),
crs=4326)
print(gdf)
fid location_name equipment geometry
>> 0 ABC tank POINT (-68.85053 -46.03444) # fid 0 and 1 have same attribs and nearly-identical geometry, so a duplicate should be removed
>> 1 ABC tank POINT (-68.85053 -46.03444)
>> 2 DEF generator POINT (-68.60402 -37.49877) # fid 2 and 3 have the same attribs but different geometry, so both should be kept
>> 3 DEF generator POINT (-69.17997 -38.91215)
>> 4 JKL tank POINT (-69.29236 -38.55543) # fid 4 and 5 have the same geometry but not identical attributes, so both are kept
>> 5 JKL generator POINT (-69.29236 -38.55543)
If I only wanted to remove duplicate records based on attributes, I could use Pandas's drop_duplicates()
function: gdf.drop_duplicates(subset=['location_name', 'equipment', 'geometry'], keep='first')
. However, because the values in the geometry
column are not exactly identical to one another, no records are dropped.
If I were just comparing two sets of coordinates to see if they're close enough to be considered identical, I could use something like
np.isclose()
and define my threshold for "sameness", but I don't know how I'd apply this sort of analysis across a gdf
where I don't know in advance which rows might be similar to one another.
How can I identify records in my gdf
with similar enough (according to a threshold) geometries and attributes, and drop those records?
Desired result:
fid location_name equipment geometry
>> 0 ABC tank POINT (-68.85053 -46.03444)
>> 2 DEF generator POINT (-68.60402 -37.49877)
>> 3 DEF generator POINT (-69.17997 -38.91215)
>> 4 JKL tank POINT (-69.29236 -38.55543)
>> 5 JKL generator POINT (-69.29236 -38.55543)