helpme
helpme

Reputation: 203

How to plot a list of Points and LINESTRING?

hello all is there a way to plot a list of LINESTRING and list of Points

for example I have

line_string = [LINESTRING (-1.15.12 9.9, -1.15.13 9.93), LINESTRING (-2.15.12 8.9, -2.15.13 8.93)]
point = [POINT (5.41 3.9), POINT (6.41 2.9)]

My goal is to have a map or graph where the it shows me where the points connect with the LINESTRING.

Thank you in advance

EDIT

Thank you all for you answers sadly when I plot it looks like. I think the issue is the fact that some LINESTRINGS have 4 points (LINESTRING (-1.15.12 9.9, -1.15.13 9.93, -5.15.13 5.53, -3.15.13 2.23)) and some have 3 points. Is there a way to plot these better?

enter image description here

Upvotes: 3

Views: 11397

Answers (3)

nightwuffle
nightwuffle

Reputation: 341

I made a library which provides a very easy to way to plot well known text strings and shapely objects. The library is called WKTPlot, and it wraps around the Bokeh library automating a lot of what @matthew-borish mentioned in their solution. What this solution would look like using WKTPlot:

from shapely.geometry import LineString, Point
from wktplot import WKTPlot

line_strings = [
    LineString([(-1.15, 0.12), (9.9, -1.15), (0.13, 9.93)]),
    LineString([(-2.15, 0.12), (8.9, -2.15), (0.13 , 8.93)]),
]
points = [Point(5.41, 3.9), Point (6.41, 2.9)]

// Create plot object
plot = WKTPlot("test1", save_dir=".")

# Add shapes using Bokeh styling arguments
# - https://docs.bokeh.org/en/latest/docs/user_guide/styling.html
for line_string in line_strings:
    plot.add_shape(line_string, line_width=3)

for point in points:
    plot.add_shape(point, line_width=7)

# Save plot to disk [./test1.html]
plot.save()

Upvotes: 1

Matthew Borish
Matthew Borish

Reputation: 3086

You can access matplotlib easily using geopandas scripting layer.

from shapely.geometry import LineString, Point
import geopandas as gpd    

line_strings = [LineString([(-1.15, 0.12), (9.9, -1.15), (0.13, 9.93)]),
                    LineString([(-2.15, 0.12), (8.9, -2.15), (0.13 , 8.93)])]
points = [Point(5.41, 3.9), Point (6.41, 2.9)]

geom = line_strings + points
gdf = gpd.GeoDataFrame(geometry=geom)

gdf.plot()

Edit, based upon your comment. You can make an interactive plot with Bokeh if you want to zoom in on certain areas.

from bokeh.plotting import figure, show

p = figure(title="interactive plot example", x_axis_label='x', y_axis_label='y')

for ls in line_strings:

    x, y = ls.coords.xy
    p.line(x, y, legend_label="lines", color="blue", line_width=2)
    

for point in points:
    
    p.circle(point.x, point.y, legend_label="points", size=5, color="red", alpha=0.5)
    

show(p)

matplotlib sample

bokeh sample

Upvotes: 6

Rob Raymond
Rob Raymond

Reputation: 31146

  • you can plot as layers
  • have demonstrated in matplotlib and folium
  • some of your geometry is invalid
import shapely.wkt
import geopandas as gpd
import pandas as pd

# line_string = ["LINESTRING (-1.15.12 9.9, -1.15.13 9.93)", "LINESTRING (-2.15.12 8.9, -2.15.13 8.93)"]
# invalid geometry - modified
line_string = ["LINESTRING (-1.15 9.9, -1.15 9.93)", "LINESTRING (-2.15 8.9, -2.15 8.93)"]
point = ["POINT (5.41 3.9)", "POINT (6.41 2.9)"]

gs_ls = gpd.GeoSeries(pd.Series(line_string).apply(shapely.wkt.loads))
gs_p = gpd.GeoSeries(pd.Series(point).apply(shapely.wkt.loads))

# matplotlib
ax = gs_ls.plot()
ax = gs_p.plot(ax=ax)

# folium
m = gs_ls.explore()
m = gs_p.explore(m=m)
m

using alternative geometry

  • with respect to what it looks like. Clearly geometry makes a difference
  • have created 6 line strings as parts of boundary of Germany (4 points). Then respective points as center of these line strings
  • just 4 points does plot well. Longer line strings are not necessary.
import geopandas as gpd
import shapely.geometry
import numpy as np

world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))

# exteriod of germany
ls = world.loc[world["iso_a3"].isin(["DEU"])].exterior.values[0]

# generate a series of linestring segments from germany bounday
gs_l = gpd.GeoSeries(
    [
        shapely.geometry.LineString(list(ls.coords)[s : s + 4])
        for s in np.random.randint(0, len(list(ls.coords)) - 4, 6)
    ], crs="epsg:4326"
)

# folium
m = gs_l.explore(style_kwds={"weight":6}, height=400, width=400)
gs_l.centroid.explore(m=m, color="red", marker_kwds={"radius":10})

# matplotlib
ax = gs_l.plot()
ax = gs_l.centroid.plot(color="red", markersize=50, ax=ax)

m

enter image description here enter image description here

Upvotes: 2

Related Questions