You can spatial joinSet the df to itself by predicate touchesgeometry as the dataframes boundary, and intersect the resulting geometriesdf with itself, select rows where ids are different:
#Save the geometry in a column
df["the_geom"]df["id"] = dfdf["id"].geometry astype(int)
#Spatial join the df to itself, by predicate touches. So adjacent polygons are joined together
sjgeometry = df.sjoin(df, how="inner", predicate="touches")
#Polygon 2 is adjacent to 1, and 4 to 1:
# sj[["id_left","id_right"]].head(2)
# id_left id_right
# 0 2.0 1.0
# 3 4.0 1.0
# sj.columns
# ['id_left', 'geometry', 'the_geom_left', 'index_right', 'id_right',
# 'the_geom_right']
#Drop duplicate joins, like id 0-1 and id 1-0. I dont know if you want to keep them or not.boundary
duplicate_maskdf = gpd.pd.DataFrame(np.sort(a=sj[["id_left","id_right"]].values, axis=-1)).duplicated().tolistoverlay()
sj = sj.loc[duplicate_mask]
#Intersect adjacent polygons, the polygons on the same row in the sj dataframe.
#The result will be line and multilines
sj[["id_left"df1=df,"id_right"]]
sj["border_lines"] = sj.apply(lambda x: x.the_geom_left.intersection(x.the_geom_right)df2=df, axis=1)
sj = sj.set_geometry("border_lines")#.explode(how="intersection")
sjdf = sjdf.drop(columns=["geometry", "the_geom_left",loc[df["id_1"] "the_geom_right",< "index_right"])df["id_2"]]
I dont get your row count but you should be able to adjust the code to get what you want.

