Inconsistency in changing/updating xtick labels and ytick labels in Plotly

Let me demonstrate with an example. Letโ€™s take the simple line plot shown here, the first figure in the Plotly user guide:

from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go

trace1 = go.Scatter(x=[1,2,3], y=[4,5,6], marker={'color': 'red', 'symbol': 104, 'size': 10}, 
                    mode="markers+lines",  text=["one","two","three"], name='1st Trace')
                                               
data=go.Data([trace1])
layout=go.Layout(title="First Plot", xaxis={'title':'x1'}, yaxis={'title':'x2'})
figure1=go.Figure(data=data,layout=layout)
init_notebook_mode(connected=True)
iplot(figure1)

enter image description here

Now, say I want to update the x-tick labels to 'A', 'B', 'C' and the ytick labels to 'E', 'F', 'G'. I can do that by updating the figure like so:

figure1['data'][0]['x']=['A', 'B', 'C']
figure1['data'][0]['y']=['E', 'F', 'G']

iplot(figure1)

enter image description here

So far so good. However, letโ€™s say I first plot the figure using matplotlib, then convert to plotly like so:

import matplotlib.pyplot as plt
import plotly.tools as tls

plt.plot([1,2,3], [4,5,6], 'r+-', markersize=10)
plt.xlabel('x2')
plt.ylabel('y2')

mpl_fig = plt.gcf()
figure2 = tls.mpl_to_plotly(mpl_fig)

init_notebook_mode(connected=True)
iplot(figure2)

enter image description here

This is relevant when, say, the library you are using to plot the figures was designed to work with matplotlib only (or maybe seaborn at max). But you want to make the plots dynamic/interactive and use them in plotly.

This time if I try to update the figure in the exact same way as before, I get a blank figure!

figure2['data'][0]['x']=['A', 'B', 'C']
figure2['data'][0]['y']=['E', 'F', 'G']

iplot(figure2)

enter image description here

Not only is it a blank figure, the xtick labels and ytick labels are also left unchanged.

When I look deeper what is contained in figure1['data'][0]['x'], I see that its a tuple:

enter image description here

And when I check what is contained in figure2['data'][0]['x'], it is also the same exact tuple:

enter image description here

Same goes for figure1['data'][0]['y'] and figure2['data'][0]['y'] - they both contain the tuple ('E', 'F', 'G').

So, whatโ€™s going on? Why does figure2 not get plotted after updating the tick labels? How can I fix it?

Hi @kristada619,

It might help to look at the display of each figure to see if we can understand whatโ€™s different about their structure. My first thought is that maybe the matplotlib-converted figure has the layout.xaxis.range and layout.yaxis.range set and that this is interfering with categorical specification.

Another approach to altering the tick labels while keeping the data coordinates numeric, is to use layout.xaxis.tickvals and layout.xaxis.ticktext. In this case

figure1.layout.xaxis.tickvals = [1, 2, 3]
figure1.layout.xaxis.tickvals = ['A', B', C']

-Jon

Hi @jmmease. Do you mean,

figure2.layout.xaxis.tickvals = [1,2,3]
figure2.layout.xaxis.ticktext = [โ€˜Aโ€™, โ€˜Bโ€™, โ€˜Cโ€™]

figure2.layout.xaxis.tickvals = [4,5,6]
figure2.layout.xaxis.ticktext = [โ€˜Eโ€™, โ€˜Fโ€™, โ€˜Gโ€™]

I tried this, and this is what I get:

iplot(figure2)
Capture

It does not display the x-ticks at all, and it plots the numeric y-ticks

The fix I have found so far by tinkering myself is to replace the layout with a blank layout essentially. For some reason, the layout of a plotly graph converted from matplotlib seems to cause updates to the figure to be not reflected. After making the layout blank (and then, if required, adding stuff to it, like the title and the axes labels as shown below), it seems to be working fine:

figure2['layout'] = {'title':'First plot', 'xaxis':{'title':'x2'}, 'yaxis':{'title':'y2'}}

figure2['data'][0]['x']=['A', 'B', 'C']
figure2['data'][0]['y']=['E', 'F', 'G']

iplot(figure2)

enter image description here

1 Like