使用图形交互Bokeh 或 Javascript修改 python 数组

问题描述

我有一个一维 numpy 数组,例如[1,6,3,2,1,4,1],我已经能够使用散景库。

我希望能够使用图形交互修改数组。

理想情况下,我希望能够一次移动 1 个值。

任何想法将不胜感激:)

Example

enter image description here

import numpy as np
import pandas as pd
from bokeh.models import ColumnDataSource,Grid,Linearaxis,Plot,Quad,Range1d,HoverTool,Panel,Tabs,Legend,LegendItem,FixedTicker,NumeralTickFormatter,SingleIntervalTicker
from bokeh.plotting import figure
from bokeh.embed import components
from bokeh.io import curdoc,show

#-------------------------------------------------------------------------------------------------
# Create Data
#-------------------------------------------------------------------------------------------------
Values= np.random.randint(0,6000,800)


def Values_to_Bins(Values,Bin_size): #takes in a numpy array of values,and the Bin size
    Min_Value = np.amin(Values)
    Max_Value =np.amax(Values)
    bins = np.arange(Min_Value,Max_Value + 2 * (Bin_size),Bin_size)  # Define bin edges
    hist_array,edges = np.histogram(Values,bins=bins)  # Create 2 arrays,hist_array represents the bin counts,edges is the bin edges
    return hist_array,edges #Returns the histogram array,and edges
# -------------------------------------------------------------------------------------------------
# STEP X: Create bokeh Histogram Plots
# -------------------------------------------------------------------------------------------------
hist_array,edges = Values_to_Bins(Values,15)

# Create a Pandas Dataframe 
bokeh_Bins = pd.DataFrame({'Values': hist_array,'left': edges[:-1],'right': edges[1:]})
Max_Initial_Bin = bokeh_Bins['Values'].max()

# Create a column showing the extent of each interval
bokeh_Bins['Bin_interval'] = ['%d to %d ms' % (left,right) for left,right in
                              zip(bokeh_Bins['left'],bokeh_Bins['right'])]

tick_vals = np.arange(Max_Initial_Bin + 1)

# Convert dataframe to column data source
src1 = ColumnDataSource(bokeh_Bins)

plot = figure(y_range=Range1d(start=0,end=Max_Initial_Bin),sizing_mode="scale_width",width=3000,height=600,title="Want to create interactive Histogram data",x_axis_label="Time (ms)",y_axis_label="Number of occurances")
plot.yaxis.ticker = FixedTicker(ticks=list(tick_vals))

plot.quad(bottom=0,top='Values',left='left',right='right',source=src1,fill_color="#939393",line_color='black',fill_alpha=0.5,hover_fill_alpha=1.0,hover_fill_color='#00E400')

# Add hover tool for when mouse is over data
hover1 = HoverTool(tooltips=[('Timeframe','@Bin_interval'),('Count','@Values')])
plot.add_tools(hover1)
original_script,original_div = components(plot)
show(plot)

解决方法

为了使用 Boken 进行交互修改,您可以添加一个 Widgets,如 sliders 和其他,其中使用这些小部件所做的任何修改都会触发相应的回调函数。您可以在以下链接中找到很好的信息:

https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html

在该链接中,您将找到大量 Python 示例。

当然,欢迎其他支持,我会给予。

,

直方图中的每个条形对应一组数据点。你需要一些规则(随机选择一个?最小的?最大的?)来移动。然后当你将它移动到另一个 bin 时,你还需要选择设置它的值(bin 中心?左边还是右边?在 bin 中均匀的某个地方)。

一旦您做出了这些选择,那么在实现以下伪代码的地方实现回调应该不会太难。

   [bin_edges,bin_counts,data_map] = histogram(data)
   [bin,y] = picked_bin() # This returns the value of your 1st mouse click
   [newbin,newy] = set_bin() # This returns the value of your 2nd mouse click
   possible_points = bin_edges[data_map] == x
   old_datum_ind = pick_one(data,possible_points)
   data[old_datum_ind] = assign_new_value(newx)

关键信息是data_map,它与数据的长度相同,但它是将数据中的每个数据映射到一个bin的索引。这让您可以轻松找出与每个 bin 对应的数据点。