我试图重新计算两个坐标之间的距离,一个是通过2个TextInput类给出的,另一个是在数据框中。我想解决这个问题,以便根据接近条件选择数据,也许选择选项,但除非根据2个TextInput输入动态更新距离,否则这些都不能工作。
我遵循文档和示例,但由于某种原因,df[‘distance’]
没有改变。
我的代码如下,我在回调中定义了一个函数来计算距离。
import numpy as np
import pandas as pd
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CustomJS, TextInput
import math
from bokeh.layouts import column, row
from bokeh.io import show
df = pd.DataFrame(np.random.rand(100,2),columns=list('Xy'))
def distance(origin, destination):
lat1, lon1 = origin
lat2, lon2 = destination
radius = 6371 # km
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
math.sin(dlon / 2) * math.sin(dlon / 2))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
d = radius * c
return d
cord_1, cord_2 = 30.56289,70.38185
df['distance'] = [distance((cord_1,cord_2),(df['X'][i],df['y'][i])) for i in range(0,len(df['X']))]
source=ColumnDataSource(df)
cord_x = TextInput(title="X-Coordinates")
cord_y = TextInput(title="Y-Coordinates")
TOOLTIPS = [
('Distance','@distance')
]
p = figure(title='Sample Distance',width = 800, height = 600,tooltips = TOOLTIPS)
p.circle(x='X',y='y',size = 10,source=source)
callback = CustomJS(args=dict(source=source, cord_x=cord_x, cord_y=cord_y),
code="""
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}
var data = source.data;
var distance = 0;
var A = cord_x.value;
var B = cord_y.value;
//apply function
for(var i = 1; i < data['X'].length ; i++) {
distance = getDistanceFromLatLonInKm(A,B,data['X'][i],data['y']);
data['distance'][i] = distance;
}
source.change.emit()
""")
source.js_on_change('data', callback)
layout = row(
p,
column(cord_x, cord_y),
)
show(layout)
所以,如果我理解这是正确的,你正在寻找动态更新cord_x
和cord_y
作为基础坐标来计算从你的数据框架中的点的距离?当工具提示中的距离改变时,坐标本身保持不变。
做了一些小更改:首先,需要将js_on_change
应用于小部件。其次,它需要调用'value'作为第一个参数。最后,你错过了data['y'][i]
中的[i]
部分。下面是完整的代码:
import numpy as np
import pandas as pd
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CustomJS, TextInput
import math
from bokeh.layouts import column, row
from bokeh.io import show
df = pd.DataFrame(np.random.rand(100,2),columns=list('Xy'))
def distance(origin, destination):
lat1, lon1 = origin
lat2, lon2 = destination
radius = 6371 # km
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
math.sin(dlon / 2) * math.sin(dlon / 2))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
d = radius * c
return d
cord_1, cord_2 = 30.56289,70.38185
df['distance'] = [distance((cord_1,cord_2),(df['X'][i],df['y'][i])) for i in range(0,len(df['X']))]
source=ColumnDataSource(df)
cord_x = TextInput(title="X-Coordinates")
cord_y = TextInput(title="Y-Coordinates")
TOOLTIPS = [
('Distance','@distance')
]
p = figure(title='Sample Distance',width = 800, height = 600,tooltips = TOOLTIPS)
p.circle(x='X',y='y',size = 10,source=source)
callback = CustomJS(args=dict(source=source, cord_x=cord_x, cord_y=cord_y),
code="""
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}
var data = source.data;
var distance = 0;
var A = cord_x.value;
var B = cord_y.value;
//apply function
for(var i = 1; i < data['X'].length ; i++) {
distance = getDistanceFromLatLonInKm(A,B,data['X'][i],data['y'][i]);
data['distance'][i] = distance;
}
source.change.emit()
""")
cord_x.js_on_change('value', callback)
cord_y.js_on_change('value', callback)
layout = row(
p,
column(cord_x, cord_y),
)
show(layout)