How to force Plot.ly Python to use a given yaxis range?

AmourK picture AmourK · May 23, 2018 · Viewed 20.5k times · Source

As you can see below, I manually define the range for each yaxis as well as setting the autorange option to be False.

However, if you graph this, you will still find the yaxis1 range is 0 to 20 rather than 0 to 25. As a result, one of the bars sticks out of the chart.

How do I make it so that I can be certain every value will be contained within the yaxis range?

Edit: Additionally, the top grid line in the second row is not showing. If I rescale slightly, it will appear again. So the issue seems to be purely graphical. Any ideas are appreciated.

from plotly import tools
fig = tools.make_subplots(rows=2, cols=2, subplot_titles=['A', 'B'], shared_xaxes=False, shared_yaxes=True)

data = [[10, 4, 15, 20.5], [3, 12, 22.2], [6.5, 12, 26.2], [18, 4.2, 22.2]]
traces = [go.Bar(x=['Type A', 'Type B', 'Type C'], y=d) for d in data]

fig.append_trace(traces[0], 1, 1)
fig.append_trace(traces[1], 1, 2)
fig.append_trace(traces[2], 2, 1)
fig.append_trace(traces[3], 2, 2)

fig['layout']['yaxis1'].update(title='', range=[0, 25], autorange=False)
fig['layout']['yaxis2'].update(title='', range=[0, 30], autorange=False)

py.iplot(fig)

Produced Chart with incorrect axis

Answer

Naren Murali picture Naren Murali · May 30, 2018

So I tried your code and was able to replicate the issue.

Reason:

The cause for this, is that, if you look at the top left graph's yaxis you can see there are 3 values [0, 10, 20], so there is a difference of 10, between each of the values. so when you set the range as [0, 25], the difference of 10 is not met, hence we not able to see 25 in the yaxis.

If we look at the graph on the bottom left's xaxis, we can see that the value 30 obeys the difference of 10, between each of the values. Thus we are able to see 30 in the yaxis!

Solution:

If you look at the plotly documentation, found here, we can use a particular property of the yaxis object to set the increment between each of the ticks, called dtick, plotly defines it as:

P.S: A personal Thank you to Maximilian Peters for aiding to find the solution!!!!

dtick (number or categorical coordinate string)
Sets the step in-between ticks on this axis. Use with tick0. Must be a positive number, or special strings available to "log" and "date" axes. If the axis type is "log", then ticks are set every 10^(n"dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. "log" has several special values; "L", where f is a positive number, gives ticks linearly spaced in value (but not position). For example tick0 = 0.1, dtick = "L0.5" will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use "D1" (all digits) or "D2" (only 2 and 5). tick0 is ignored for "D1" and "D2". If the axis type is "date", then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set dtick to 86400000.0. "date" also has special values "M" gives ticks spaced by a number of months. n must be a positive integer. To set ticks on the 15th of every third month, set tick0 to "2000-01-15" and dtick to "M3". To set ticks every 4 years, set dtick to "M48"

So, when we set the dtick as 5 and the range as [0,25] we will get the expected result!

Please tryout the below code and let me know if your issue is resolved completely!

import pandas as pd
import plotly.offline as py_offline
import plotly.graph_objs as go
py_offline.init_notebook_mode()
from plotly import tools
fig = tools.make_subplots(rows=2, cols=2, subplot_titles=['A', 'B'], shared_xaxes=False, shared_yaxes=True)

data = [[10, 4, 15, 20.5], [3, 12, 22.2], [6.5, 12, 26.2], [18, 4.2, 22.2]]
traces = [go.Bar(x=['Type A', 'Type B', 'Type C'], y=d) for d in data]

fig.append_trace(traces[0], 1, 1)
fig.append_trace(traces[1], 1, 2)
fig.append_trace(traces[2], 2, 1)
fig.append_trace(traces[3], 2, 2)

fig['layout']['yaxis1'].update(title='', range=[0, 25], dtick=5, autorange=False)
fig['layout']['yaxis2'].update(title='', range=[0, 30], autorange=False)

py_offline.iplot(fig)