Raven Cheuk
Raven Cheuk

Reputation: 3053

Plotly failed to return information for selected data points for multiple tracers

In this example, they plot everything in a single go.Scatter tracer and then they can use the selection_fn to get the information for the selected points.

I want to do similar thing with my dataset with consists of 3 clusters. In order to make the clusters easier to be seen, I use one tracer for one class. Therefore, I try to modify the example code to adapt to my dataset as shown below.

import plotly.plotly as py
import plotly.graph_objs as go
from plotly.tools import set_credentials_file
import plotly.offline as py

import pandas as pd
import numpy as np
from ipywidgets import interactive, HBox, VBox

from sklearn.datasets import make_blobs

X, y = make_blobs(30,random_state=101)

py.init_notebook_mode()

f = go.FigureWidget([go.Scatter(y = X[y==0][:,1], x = X[y==0][:,0], mode = 'markers'), 
                     go.Scatter(y = X[y==1][:,1], x = X[y==1][:,0], mode = 'markers'),
                     go.Scatter(y = X[y==2][:,1], x = X[y==2][:,0], mode = 'markers')])
scatter = f.data[0]
N = len(X)

# Create a table FigureWidget that updates on selection from points in the scatter plot of f
t = go.FigureWidget([go.Table(
    header=dict(values=['x','y','class'],
                fill = dict(color='#C2D4FF'),
                align = ['left'] * 5),
    cells=dict(values=[X[:,0], X[:,1], y],
               fill = dict(color='#F5F8FF'),
               align = ['left'] * 5))])

def selection_fn(trace,points,selector):
    print(points.point_inds)
    t.data[0].cells.values = [X[points.point_inds,0], X[points.point_inds,1], y[points.point_inds]]

scatter.on_selection(selection_fn)

# Put everything together
VBox((HBox(),f,t))

Wrong Behaviors 1: Wrong information returned

When selecting two data points from trace 0, it does return 2 information to me, yet it's wrong.

enter image description here enter image description here

Wrong Behaviors 2: No information returned

When selecting data points from tracer 1 and 2, it doesn't even return the information enter image description here enter image description here

After a brief debugging, I notices that there is mismatch in the index for each tracer and the complete dataset. This code can return the index from tracer 0 only, however, when it passes the index to the full dataset, it gives you the mis-matached information for the points. When selecting points from tracer 1 and 2, it can't even return the index, thus no information can be extracted.

Although I understand the problem, I don't know how to modify the code since I am still new to plotly.

Upvotes: 3

Views: 1229

Answers (1)

Raven Cheuk
Raven Cheuk

Reputation: 3053

After trying it for several days, I have figured out a hack to achieve it. (Maybe someone can still provide a better way?)

The trick is to create 3 lists for each of the column in the table, and the append the data of the selected points to the list, and update the table in the end.

Here's the complete code.

X, y = make_blobs(30,random_state=101)

py.init_notebook_mode()

f = go.FigureWidget([go.Scatter(y = X[y==0][:,1], x = X[y==0][:,0], text=y[y==0], mode = 'markers', name='class 0'), 
                     go.Scatter(y = X[y==1][:,1], x = X[y==1][:,0], text=y[y==1], mode = 'markers', name='class 1'),
                     go.Scatter(y = X[y==2][:,1], x = X[y==2][:,0], text=y[y==2], mode = 'markers', name='class 2')])


# Create a table FigureWidget that updates on selection from points in the scatter plot of f
t = go.FigureWidget([go.Table(
    header=dict(values=['x','y', 'class'],
                fill = dict(color='#C2D4FF'),
                align = ['left'] * 5),
    cells=dict(values=[X[:,0], X[:,1], y],
               fill = dict(color='#F5F8FF'),
               align = ['left'] * 5))])

# def data_append(trace,points,selector):
#     X1 = []
#     X2 = []
#     c = []


X1 = []
X2 = []
data_cluster = []
num_called = 0
def selection_fn(trace,points,selector):
    global num_called
    global X1, X2, data_cluster
    if num_called == 3: # number of scatters
        num_called = 0
        X1 = []
        X2 = []
        data_cluster = []
    X1.extend(trace['x'][points.point_inds])
    X2.extend(trace['y'][points.point_inds])
    data_cluster.extend(trace['text'][points.point_inds])
    t.data[0].cells.values = [X1, X2,data_cluster]
    num_called +=1
for scatter in f.data:
    scatter.on_selection(selection_fn)

# Put everything together
VBox((HBox(),f,t))

Output of the code

enter image description here enter image description here

As you can see, the table return exactly the information for the three selected data points.

Upvotes: 2

Related Questions