Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How to get data from linked brushes in mlpd3, Bokeh, Plotly?

Using the code below I can get a 2x2 graph with 4 plots. With brushes, I can select some data points. The question I have is how do get the selected data points as a JSON array or cvs. This code uses mlpd3, but bokeh can do similar selections with brushes.. But there is no example of selecting the data points. I am trying to get selected data as object to continue processing with python. It would be nice to see the data in a cell.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mat
import mpld3

mpld3.enable_notebook()


from mpld3 import plugins

fig, ax = plt.subplots(2, 2, figsize=(10, 8))
fig.subplots_adjust(hspace=0.1, wspace=0.1)
ax = ax[::-1]

X = np.random.normal(size=(2, 100))
for i in range(2):
    for j in range(2):
        ax[i, j].xaxis.set_major_formatter(plt.NullFormatter())
        ax[i, j].yaxis.set_major_formatter(plt.NullFormatter())
        points = ax[i, j].scatter(X[j], X[i])

plugins.connect(fig, plugins.LinkedBrush(points))

Bokeh has similar behavior in CustomJS for Selections

http://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html#userguide-interaction-jscallbacks-customjs-interactions

Whichever one is easier to extract the selected item -- would work.. If there is a Plotly solution, that would also work.

like image 792
Merlin Avatar asked Jun 13 '17 20:06

Merlin


2 Answers

You can get the selected data from a Plotly chart by using Plotly's new Dash framework.

There is an example in the docs here under "Graph Crossfiltering" https://plot.ly/dash/getting-started-part-2

I've pasted the full example below just for preservation of history.

In each of the callbacks below, you have access to the either the selected points, the points that you just hovered over, or the points that you just clicked on. This app simply displays the values of the points in the app, but you could do anything with the points (e.g. compute something else).

example gif of selecting data in a Dash app

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import json

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Graph(
        id='basic-interactions',
        figure={
            'data': [
                {
                    'x': [1, 2, 3, 4],
                    'y': [4, 1, 3, 5],
                    'text': ['a', 'b', 'c', 'd'],
                    'customdata': ['c.a', 'c.b', 'c.c', 'c.d'],
                    'name': 'Trace 1',
                    'mode': 'markers',
                    'marker': {'size': 12}
                },
                {
                    'x': [1, 2, 3, 4],
                    'y': [9, 4, 1, 4],
                    'text': ['w', 'x', 'y', 'z'],
                    'customdata': ['c.w', 'c.x', 'c.y', 'c.z'],
                    'name': 'Trace 2',
                    'mode': 'markers',
                    'marker': {'size': 12}
                }
            ]
        }
    ),

    html.Div([
        dcc.Markdown("""
            **Hover Data**

            Mouse over values in the graph.
        """.replace('   ', '')),
        html.Pre(id='hover-data')
    ], style=styles['column']),

    html.Div([
        dcc.Markdown("""
            **Click Data**

            Click on points in the graph.
        """.replace('    ', '')),
        html.Pre(id='click-data'),
    ], style=styles['column']),

    html.Div([
        dcc.Markdown("""
            **Selection Data**

            Choose the lasso or rectangle tool in the graph's menu
            bar and then select points in the graph.
        """.replace('    ', '')),
        html.Pre(id='selected-data'),
    ])
])


@app.callback(
    Output('hover-data', 'children'),
    [Input('basic-interactions', 'hoverData')])
def display_hover_data(hoverData):
    #
    # This is where you can access the hover data
    # This function will get called automatically when you hover over points
    # hoverData will be equal to an object with that data
    # You can compute something off of this data, and return it to the front-end UI
    # 


    return json.dumps(hoverData, indent=2)


@app.callback(
    Output('click-data', 'children'),
    [Input('basic-interactions', 'clickData')])
def display_click_data(clickData):
    # Similarly for data when you click on a point
    return json.dumps(clickData, indent=2)


@app.callback(
    Output('selected-data', 'children'),
    [Input('basic-interactions', 'selectedData')])
def display_selected_data(selectedData):
    # Similarly for data when you select a region
    return json.dumps(selectedData, indent=2)


if __name__ == '__main__':
    app.run_server(debug=True)
like image 57
Chris P Avatar answered Oct 24 '22 03:10

Chris P


This is outside of ipython but you can run flask or django in conjunction with d3.js and jquery to get the data back into python.

like image 32
pyCthon Avatar answered Oct 24 '22 02:10

pyCthon