python - 如何在散点图盒上绘制圆形半径图(Plotly Python)

标签 python plotly mapbox haversine

我想根据圆半径(以公里为单位)检索最近的坐标点,并将结果绘制在散点图框上。但我不知道如何绘制圆形半径。有人知道如何绘制圆形半径吗?

到目前为止,我的结果只是圆半径中的数据,没有圆的形状。这是我的代码

import plotly.graph_objects as go
import plotly.express as px
from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):

    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371
    return c * r

center_point = pd.DataFrame({'Longitude':[long_input], 'Latitude':[lat_input]})
test_point = df_latlong[['Longitude','Latitude']].reset_index().drop('index',axis=1)

lat1 = center_point['Latitude'][0]
lon1 = center_point['Longitude'][0]

df_nearest = []
for i, (index, row) in enumerate(df_latlong.iterrows()):
    lat2 = test_point['Latitude'][i]
    lon2 = test_point['Longitude'][i]
    a = haversine(lon1, lat1, lon2, lat2)
    df_nearest.append(a)

df_latlong['Distance'] = df_nearest
df_radius = df_latlong[df_latlong['Distance'] <= 5] #5 kilometers for radius 

fig_map3 = px.scatter_mapbox(df_radius, lon=df_radius['Longitude'], lat=df_radius['Latitude'],
                             hover_name='#WELL', zoom=9, width=300, height=500)

fig_map3.update_layout(mapbox_style='open-street-map', margin={'r':0, 't':0, 'l':0, 'b':0})

fig_map3.show()

它具有基于我在 center_point 中定义的质心的圆形半径。我怎样才能画出这样的黑色圆圈?半径有5公里。任何想法?谢谢!

最佳答案

首先,我在与屏幕截图中显示的数据相同的地理区域中创建了一些示例数据。

然后,我们可以使用 the approximation 计算半径为 r 的圆的(纬度、经度)点、圆心和样本点数量。由 @Stéphane 给出(对于你的问题,你想要的中心点周围 5 公里的半径足够小,这个近似值可以很好地保持)。

注意:我尝试[失败]使用geog.propogate计算圆的精确坐标,如here所述。 ,但它没有为围绕中心坐标的圆生成正确的坐标。

然后您可以将圆的(纬度、经度)点传递给 go.Scattermapbox,将模式设置为“线条”,并将轨迹添加到您的图形中。

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from math import radians, cos, sin, asin, sqrt, pi

def haversine(lon1, lat1, lon2, lat2):

    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371
    return c * r

## create a sample dataframe to reproduce your data
lat_input, long_input = -0.622929, 117.575513,

lat_min, lat_max = -0.59, -0.68
long_min, long_max = 117.543, 117.614

np.random.seed(42)
df_latlong = pd.DataFrame({
    'Latitude': np.random.uniform(lat_min, lat_max, size=20),
    'Longitude': np.random.uniform(long_min, long_max, size=20),
    '#WELL': ["TN-test"]*20
})

center_point = pd.DataFrame({'Longitude':[long_input], 'Latitude':[lat_input]})
test_point = df_latlong[['Longitude','Latitude']].reset_index().drop('index',axis=1)

lat1 = center_point['Latitude'][0]
lon1 = center_point['Longitude'][0]

df_nearest = []
for i, (index, row) in enumerate(df_latlong.iterrows()):
    lat2 = test_point['Latitude'][i]
    lon2 = test_point['Longitude'][i]
    a = haversine(lon1, lat1, lon2, lat2)
    df_nearest.append(a)

df_latlong['Distance'] = df_nearest
df_radius = df_latlong[df_latlong['Distance'] <= 5] #5 kilometers for radius 

fig_map3 = px.scatter_mapbox(df_radius, lon=df_radius['Longitude'], lat=df_radius['Latitude'],
                             hover_name='#WELL', zoom=9, width=300, height=500)

radius = 5 * 1000 # m - the following code is an approximation that stays reasonably accurate for distances < 100km

# parameters
N = 360 # number of discrete sample points to be generated along the circle

# generate points
circle_lats, circle_lons = [], []
for k in range(N):
    # compute
    angle = pi*2*k/N
    dx = radius*cos(angle)
    dy = radius*sin(angle)
    circle_lats.append(lat1 + (180/pi)*(dy/6378137))
    circle_lons.append(lon1 + (180/pi)*(dx/6378137)/cos(lat1*pi/180))
circle_lats.append(circle_lats[0])
circle_lons.append(circle_lons[0])

fig_map3.add_trace(go.Scattermapbox(
    lat=circle_lats,
    lon=circle_lons,
    mode='lines',
    marker=go.scattermapbox.Marker(
        size=1, color="BlueViolet"
    ),
))

fig_map3.update_layout(mapbox_style='open-street-map', margin={'r':0, 't':0, 'l':0, 'b':0}, width=500)

fig_map3.show()

关于python - 如何在散点图盒上绘制圆形半径图(Plotly Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74793322/

相关文章:

python - 增加大小/参数的递归循环(哈密尔顿路径?)Python

javascript - plotly 更新数据

javascript - 如何使用 Leaflet 的 for 循环来制作圆圈?

python - 有人有通过 Data Flow Python SDK 将输出写入 SFTP 的经验吗?

python - 导入 StanfordNER Tagger Google Colab

javascript - Plotly.js - 在值之间设置刻度

javascript - 重置 Mapbox 中的所有标记层

ios - 在mapbox ios中的标记下添加文本

python - python有转换运算符吗?

python - 如何从图中删除 plotly logo ("Produced with plotly")