本文介绍了使用python在scattermapbox中的点周围绘制一个多边形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!
问题描述
I am using plotlys scattermapbox to plot points on a map. I'd like to draw the polygon that cover 'x' mile
radius from a POI.
dcc.Graph(id="map-graph"),
@application.callback([
Output("map-graph", "figure"),
],
[
Input("address", "value"),
Input("type", "value")
]
)
def update_graph(address, type):
for i, row in df.iterrows():
lat = row["Lat"]
lng = row["Long"]
data.append({
"type": "scattermapbox",
"lat": [lat],
"lon": [lng],
"name": "Location",
"showlegend": False,
"hoverinfo": "text",
"mode": "markers",
"marker": {
"symbol": "circle",
"size": 8,
"opacity": 0.8,
"color": "black"
}
}
)
# Plot POI
POI_Lat = 37.785908
POI_Long = -122.400803
data.append({
"type": "scattermapbox",
"lat": [POI_Lat],
"lon": [POI_Long],
"marker": {
"symbol": "circle,
"size": 28,
"opacity": 0.7,
"color": "rgb(128, 128, 128)"
}
}
)
df
is a pandas dataframe that includes coordinates for locations within x miles
of POI. How do I update the map-graph
to draw a polygon that covers all the points?
Adding a layer to layout dictionary:
gdf = circles(Lat, Long, radius=1609.34)
print(gdf['geometry'][0])
POLYGON ((385272.0167249573 3768678.19769511, 385264.2673129799 3768520.454790493,.......))
layout = {
"autosize": True,
"hovermode": "closest",
"mapbox": {
"accesstoken": MAPBOX_KEY,
"bearing": 0,
"center": {
"lat": layout_lat,
"lon": layout_lon
},
"layers": [
{
"source": json.loads(gdf.geometry.to_json()),
"below": "traces",
"type": "line",
"color": "purple",
"line": {"width": 1.5},
}
],
"pitch": 0,
"zoom": zoom,
"style": "outdoors",
},
"margin": {
"r": 0,
"t": 0,
"l": 0,
"b": 0,
"pad": 0
}
}
解决方案
- based on answer to this duplicate question Obtain coordinates of a Polygon / Multi-polygon around a point in python
- no sample data provided in question, so I've used UK hospital data
- have created a helper function
poi_poly()
. NB radius is in meters as per UTM geometry - UTM geometry is used to create a polygon of specified radius
- markers are then intersected with this polygon. Then get the convex hull
- have provided option to return radius polygon as well, in example below I've returned this to demonstrate that the convex hull polygon is within the radius of the POI
import shapely.geometry
import pandas as pd
import geopandas as gpd
import requests, io, json
import plotly.express as px
import random
def poi_poly(
df,
radius=10 ** 5,
poi={"Longitude": 0.06665166467428207, "Latitude": 51.19034957885742},
lon_col="Longitude",
lat_col="Latitude",
include_radius_poly=False,
):
# generate a geopandas data frame of the POI
gdfpoi = gpd.GeoDataFrame(
geometry=[shapely.geometry.Point(poi["Longitude"], poi["Latitude"])],
crs="EPSG:4326",
)
# extend point to radius defined (a polygon). Use UTM so that distances work, then back to WSG84
gdfpoi = (
gdfpoi.to_crs(gdfpoi.estimate_utm_crs())
.geometry.buffer(radius)
.to_crs("EPSG:4326")
)
# create a geopandas data frame of all the points / markers
if not df is None:
gdf = gpd.GeoDataFrame(
geometry=df.loc[:, ["Longitude", "Latitude"]]
.dropna()
.apply(
lambda r: shapely.geometry.Point(r["Longitude"], r["Latitude"]), axis=1
)
.values,
crs="EPSG:4326",
)
else:
gdf = gpd.GeoDataFrame(geometry=gdfpoi)
# create a polygon around the edges of the markers that are within POI polygon
return pd.concat(
[
gpd.GeoDataFrame(
geometry=[
gpd.sjoin(
gdf, gpd.GeoDataFrame(geometry=gdfpoi), how="inner"
).unary_union.convex_hull
]
),
gpd.GeoDataFrame(geometry=gdfpoi if include_radius_poly else None),
]
)
# get some public addressess - hospitals. data that can be scattered
dfhos = pd.read_csv(
io.StringIO(
requests.get("http://media.nhschoices.nhs.uk/data/foi/Hospital.csv").text
),
sep="",
engine="python",
)
# generate polygon of markers within 5 mile radius of Point of Interest
poi = dfhos.loc[random.randint(0, len(dfhos) - 1), ["Longitude", "Latitude"]].to_dict()
gdf = poi_poly(dfhos, poi=poi, radius=1609.34 * 5, include_radius_poly=True)
fig = (
px.scatter_mapbox(
dfhos,
lat="Latitude",
lon="Longitude",
color="Sector",
hover_data=["OrganisationName", "Postcode"],
)
.update_traces(marker={"size": 10})
.update_layout(
mapbox={
"style": "open-street-map",
"zoom": 9,
"center": {"lat": poi["Latitude"], "lon": poi["Longitude"]},
"layers": [
{
"source": json.loads(gdf.geometry.to_json()),
"below": "traces",
"type": "line",
"color": "purple",
"line": {"width": 1.5},
}
],
},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
)
fig.show()
draw just a circle polygon
poi_poly()
has been updated. DataFrame is no longer mandatory for finding markers within POI- simple example of creating a circle (actually a polygon) centred on a single set of GPS co-ordinates
import plotly.graph_objects as go
poi = {"Latitude": 37.785908, "Longitude": -122.400803}
go.Figure(go.Scattermapbox()).update_layout(
mapbox={
"style": "open-street-map",
"zoom": 9,
"center": {"lat": poi["Latitude"], "lon": poi["Longitude"]},
"layers": [
{
"source": json.loads(poi_poly(None, poi=poi, radius=1609).to_json()),
"below": "traces",
"type": "line",
"color": "purple",
"line": {"width": 1.5},
}
],
},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
这篇关于使用python在scattermapbox中的点周围绘制一个多边形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!
本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!