For intersections in GeoPandas, it is better to use a spatial-join (see More Efficient Spatial join in Python without QGIS, ArcGIS, PostGIS, etc or How to efficiently determine which of thousands of polygons intersect with a linestring [duplicate]
import geopandas as gpd
parcels = gpd.read_file('parcels.shp')
roads = gpd.read_file('roads.shp')
intersections= gpd.sjoin(parcels, roads, how="left", op='intersects')
intersections.head()
parcel geometry index_right road
0 Parcel 1 POLYGON ((-0.6824583866837387 0.78233034571062... 0.0 Road 1
1 Parcel 2 POLYGON ((-0.09859154929577452 0.3239436619718... NaN Nan
2 Parcel 3 POLYGON ((-0.9103713188220229 -0.1062740076824... 1.0 Road 2
3 Parcel 4 POLYGON ((0.2266325224071704 0.620998719590268... 0.0 Road 1
With your solution
road = roads.unary_union
parcels['road_intersection'] = parcels.intersects(road)
parcels
parcel geometry index_left road_intersection
0 Parcel 1 POLYGON ((-0.6824583866837387 0.78233034571062... 0 True
1 Parcel 2 POLYGON ((-0.09859154929577452 0.3239436619718... 1 False
2 Parcel 3 POLYGON ((-0.9103713188220229 -0.1062740076824... 2 True
3 Parcel 4 POLYGON ((0.2266325224071704 0.620998719590268... 3 True
EDIT: The following answer only works for the 1-D case. To extend it to 2-D, you will need to parameterize your links by the along-road distance, and replace the x-coordinate with the parameterized length. However, I'm fairly confident this is doable much simpler with Geopandas.
It would be too hard to give hints in the comments, so here's a script that should give you what you want. It's not written for efficiency--probably you could get geopandas to do what you want with some finegaling, but here ya go. It's also not written very generally, but that could be done if you have more than one attribute.
import geopandas as gpd
from shapely.geometry import LineString
import numpy as np
slgeom = [[(0,0),(7,0)],[(7,0),(13,0)],[(13,0),(15,0)],[(15,0),(19,0)]]
geoms = []
for s in slgeom:
geoms.append(LineString(s))
properti = ['a','b','c','d']
split_lines = gpd.GeoDataFrame(geometry=geoms)
split_lines['property'] = properti
olgeom = [[(0,0),(5,0)],[(5,0),(7,0), (10,0)],[(10,0),(13,0),(15,0)],[(15,0),(19,0)]]
geoms = []
for o in olgeom:
geoms.append(LineString(o))
susc = [1,2,3,4]
original_lines = gpd.GeoDataFrame(geometry=geoms)
original_lines['susc'] = susc
# Do split lines
xs1 = []
attrib1 = []
for g, a in zip(split_lines.geometry.values, split_lines.property.values):
x = g.coords.xy[0].tolist()
xs1.extend(x)
try:
attrib1[-1] = a
except:
pass
attrib1.extend([a for l in range(len(x))])
# Do originals
xs2 = []
attrib2 = []
for g, a in zip(original_lines.geometry.values, original_lines.susc.values):
x = g.coords.xy[0].tolist()
xs2.extend(x)
try:
attrib2[-1] = a
except:
pass
attrib2.extend([a for l in range(len(x))])
# Create numpy array for sorting
allxs = list(set(xs1 + xs2))
x_forsort = []
a1_forsort = []
a2_forsort = []
for x in allxs:
try:
idx = xs1.index(x)
a1_forsort.append(attrib1[idx])
except:
a1_forsort.append(None)
try:
idx = xs2.index(x)
a2_forsort.append(attrib2[idx])
except:
a2_forsort.append(None)
forsort = np.transpose(np.array([allxs, a1_forsort, a2_forsort]))
# Now sort based on x value (1st column)
sorteds = forsort[forsort[:,0].argsort()]
# Work through the sorted lists to create segments with the appropriate attributes
# Store results in a dictionary
output = dict()
output['geometry'] = []
output['attrib_1'] = []
output['attrib_2'] = []
for i in range(len(sorteds)-1):
# Store shapely linestring
output['geometry'].append(LineString([(sorteds[i,0],0),(sorteds[i+1,0],0)]))
# Store attributes
if i == 0:
output['attrib_1'].append(sorteds[i,1])
output['attrib_2'].append(sorteds[i,2])
else:
if sorteds[i,1] is None:
output['attrib_1'].append(output['attrib_1'][-1])
else:
output['attrib_1'].append(sorteds[i,1])
if sorteds[i,2] is None:
output['attrib_2'].append(output['attrib_2'][-1])
else:
output['attrib_2'].append(sorteds[i,2])
# Convert back to geopandas dataframe
out_gdf = gpd.GeoDataFrame(output)
out_gdf.crs = original_lines.crs
Result:
out_gdf
Out[185]:
attrib_1 attrib_2 geometry
0 a 1 LINESTRING (0 0, 5 0)
1 a 2 LINESTRING (5 0, 7 0)
2 b 2 LINESTRING (7 0, 10 0)
3 b 3 LINESTRING (10 0, 13 0)
4 c 3 LINESTRING (13 0, 15 0)
5 d 4 LINESTRING (15 0, 19 0)
Best Answer
With the solution of How to find which points intersect with a polygon in geopandas? and your data
And