Hello,
The following code snippet works great in my Jupyter notebook. It successfully displays a plotly scatter graph, and when I hover over any one of the points it correctly displays the title of an article that the point corresponds to:
import chart_studio.plotly as py
import chart_studio.tools as tools
import plotly.figure_factory as ff
import plotly.graph_objects as go
spectral = ["#E69F00", "#56B4E9", "#009E73", "#F0E442", "#D55E00", "#0072B2", "#CC79A7"]
traces = []
data = list(zip(processed_articles_pca, df.title.tolist(), df.cluster.tolist()))
for i in range(n_clusters):
# Assign the pca feature values, x[0] for each point in cluster n, x[2]
point_slice = np.asarray([x[0] for x in data if x[2] == i])
# Assign the titles for each point, x[1] in cluster n, x[2]
title_slice = [x[1] for x in data if x[2] == i]
# Regardless of the number of pca components, assign the pca values of index 0 to x,
# and index 1 to y, and set color equal to the corresponding cluster index color
trace = go.Scatter(x = point_slice[:, 0], y = point_slice[:, 1], text = title_slice,
hoverinfo = 'text',
marker = dict(size = 16, color = spectral[i], showscale = False),
mode = 'markers', name = 'cluster {}'.format(i))
traces.append(trace)
layout = go.Layout(title = 'Clustering of magazine Articles',
xaxis = dict(title = 'X PCA value', titlefont = dict(size = 18, color='#7f7f7f')),
yaxis = dict(title = 'Y PCA value', titlefont = dict(size = 18, color='#7f7f7f')))
fig = go.Figure(data = traces, layout = layout)
py.iplot(fig, filename = 'td_medium_nlp_2')
Now I would like to enhance the code above, such that when a user clicks on any point in the scatter graph, a corresponding URL is opened in a separate web browser tab (i.e., each point corresponds to a title of an article and a URL that are both stored in my DataFrame).
I wrote the following callback function:
# Create our callback function
def open_url(trace, points, selector):
if points.point_inds:
ind = points.point_inds[0]
url = df.url.iloc[ind]
webbrowser.open_new_tab(url)
And have tried a variety of ways to have it invoked, but none of them work. For example:
fig = go.FigureWidget(data = traces, layout = layout)
for trace in traces:
scatter = trace
scatter.on_click(open_url, True)
fig
Not only does this not work, but when I try to convert the plotly scatter graph to a FigureWidget, the underlying scatter graph no longer is displayed.
The one plotly page that addresses Click Events in Python (https://plot.ly/python/click-events/#reference) has an example, that, when I copy it into a Jupyter notebook cell, also displays nothing.
I read the help text at the bottom of the page that says,
βCallbacks will only be triggered when the trace belongs to a instance of plotly.graph_objs. FigureWidget and it is displayed in an ipywidget context. Callbacks will not be triggered on figures that are displayed using plot/iplot.β
So I tried displaying the scatter graph in the context of an ipywidget context, but, again, nothing is displayed:
@interact(n_clusters = widgets.IntSlider(min = 2, max = 7, step = 1, value = 3))
def display_interactive_clusters(n_clusters):
spectral = ["#E69F00", "#56B4E9", "#009E73", "#F0E442", "#D55E00", "#0072B2", "#CC79A7"] # generate color dict
traces = []
data = list(zip(processed_articles_pca, df.title.tolist(), df.cluster.tolist()))
for i in range(n_clusters):
# Assign the pca feature values, x[0] for each point in cluster n, x[2]
point_slice = np.asarray([x[0] for x in data if x[2] == i])
# Assign the titles for each point, x[1] in cluster n, x[2]
title_slice = [x[1] for x in data if x[2] == i]
# Regardless of the number of pca components, assign the pca values of index 0 to x,
# and index 1 to y, and set color equal to the corresponding cluster index color
trace = go.Scatter(x = point_slice[:, 0], y = point_slice[:, 1], text = title_slice,
hoverinfo = 'text',
marker = dict(size = 16, color = spectral[i], showscale = False),
mode = 'markers', name = 'cluster {}'.format(i))
traces.append(trace)
layout = go.Layout(title = 'Clustering of magazine Articles',
xaxis = dict(title = 'X PCA value', titlefont = dict(size = 18, color='#7f7f7f')),
yaxis = dict(title = 'Y PCA value', titlefont = dict(size = 18, color='#7f7f7f')))
fig = go.FigureWidget(data = traces, layout = layout)
for trace in traces:
scatter = trace
scatter.on_click(open_url, True)
fig
Can someone help me figure out what I am doing wrong? My goals are to:
- Display my scatter graph as a FigureWidget such that I am not using iplot (per the documentation).
- Successfully add an on_click() callback function that gets invoked when a user clicks on the points in the scatter graph.
Thank you.