4

I'm having a GeoDataFrame of lines and a GeoDataFrame of polygons. The polygons have an attribute with the altitude of that polygon.

For each line, I want to find in what polygon it is located. As output I would like to have the GeoDataFrame of lines, with the altitude attribute of the accessory polygon added to each row (each row is a line).

Below code gives the desired output for most lines.

output = gpd.sjoin(lines, polygons, how='left', op='within')

I say this works for most lines, as it does not work for lines which are located in multiple polygons, shown blue in attached image. For these lines, it gives a NaN value for the attributes. However, I would like it to find the attributes of both polygons, and eventually I keep the lowest altitude of the matched polygons.

Hopefully I made myself clear. Could anyone explain how I can do this?


Below I explain what I already tried, but this is a bit messy and maybe not the right direction:

As solution, I tried to iterate over each row of the polygon GeoDataFrame (from lowest altitude to highest), and then do the spatial join, only with lines which are not yet matched. But this didn't work for me, as the spatial join didn't work on single rows of the GeoDataFrame (crs issue).

polygons= polygons.sort_values(by=['altitude'])
output = None
for index, row in polygons.iterrows():
 if output is not None:
 toappend = gpd.sjoin(newlines, row, how='left', op='within')
 newlines = toappend[toappend['altitude'].isna()]
 output = output.append(toappend.dropna())
 else:
 output = gpd.sjoin(lines, row, how='left', op='within')
 newlines = output[output['altitude'].isna()]

AttributeError: 'Series' object has no attribute 'crs'

The blue lines are located in multiple polygons, which gives a NaN result for the spatial join, op='within'

asked May 4, 2020 at 16:02

1 Answer 1

4

Try sorting by altitude (in my example called _mean) and drop duplicates on line id:

import geopandas as gpd
polyshape = '/home/bera/GIS/Data/testdata/polygons.shp'
lineshape = '/home/bera/GIS/Data/testdata/lines.shp'
polydf = gpd.read_file(polyshape)
linedf = gpd.read_file(lineshape)
newdf = gpd.sjoin(polydf, linedf)
newdf2 = newdf.sort_values('_mean', ascending=True).drop_duplicates('id')
>>newdf2[['_mean','id']]
Out[12]: 
 _mean id
 0 34.0 22
 0 34.0 44
 1 41.0 55

enter image description here

answered May 4, 2020 at 16:54
1
  • Nice! Please accept by answer with the checkbox Commented May 6, 2020 at 7:19

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.