[파이썬] bokeh 그래프 내부 드래그 및 드롭

Bokeh is a popular Python library for creating interactive visualizations and plots. One of the powerful features of Bokeh is the ability to create draggable and droppable elements within a graph. In this blog post, we will explore how to implement this feature in your Bokeh graphs.

Setting up the Environment

To begin, make sure you have Bokeh installed in your Python environment. You can install it using pip:

pip install bokeh

Creating the Graph

Let’s start by creating a simple scatter plot using Bokeh. We will use the built-in figure function to create a blank canvas, and then add a scatter glyph to display our data points.

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource

# Create a blank canvas
p = figure()

# Add scatter glyphs
x = [1, 2, 3, 4, 5]
y = [5, 4, 3, 2, 1]
source = ColumnDataSource(data=dict(x=x, y=y))
p.circle('x', 'y', source=source, size=10)

# Show the graph
show(p)

This will create a basic scatter plot with data points. However, currently, there is no interaction available.

Implementing Drag and Drop

To enable dragging and dropping within our graph, we will utilize the Drag and Drop tools provided by Bokeh. These tools allow us to define callbacks that are triggered when a draggable element is dropped onto a droppable element.

from bokeh.models import CustomJS, TapTool, Drag, Drop

# Create a callback for the drop event
drop_callback = CustomJS(args=dict(source=source), code="""
    const data = source.data;
    const index = cb_data.index;
    const droppedData = cb_data.data_transfer.data;
    const droppedX = parseFloat(droppedData.get('x'));
    const droppedY = parseFloat(droppedData.get('y'));
  
    // Update the dropped data point
    data.x[index] = droppedX;
    data.y[index] = droppedY;
  
    // Trigger an update in the graph
    source.change.emit();
""")

# Add the drop tool to the graph
drop_tool = Drop(callback=drop_callback)
p.add_tools(drop_tool)

# Create a callback for the drag event
drag_callback = CustomJS(args=dict(source=source), code="""
    const data = source.data;
    const index = cb_data.index;
  
    // Get the dragged data point
    const draggedX = data.x[index];
    const draggedY = data.y[index];
  
    // Set the dragged data as text in the data transfer object
    const dt = cb_data.data_transfer;
    dt.setData('x', draggedX.toString());
    dt.setData('y', draggedY.toString());
""")

# Add the drag tools to the graph
drag_tool = Drag(callback=drag_callback)
p.add_tools(drag_tool)

# Show the graph
show(p)

In this code, we define a drop_callback function that is triggered when a data point is dropped onto our graph. This callback updates the dropped data point’s coordinates and triggers an update in the graph.

We also define a drag_callback function that is triggered when a data point is being dragged. This callback sets the dragged data point as text in the data transfer object.

Finally, we create instances of the Drop and Drag tools and add them to our graph using the add_tools method.

Conclusion

Implementing draggable and droppable elements within a Bokeh graph is a great way to enhance interactivity and user experience. By utilizing the Drag and Drop tools, you can enable your users to manipulate data points directly within the graph, making it easier to explore and analyze data.

Remember to explore the Bokeh documentation for more advanced features and examples. Happy coding!