Skip to content

Secondary_y axis default limit (top) & bound (upper) not matching ticks #5560

Closed

Description

@esvhd

Hi,

I raised this on SO see link here. The comments there provide clarity on this issue.

Started seeing this after I upgraded to 1.5 - but not sure if this is an issue just for 1.5.

The following code shows that, with the default settings, the secondary (RHS) y axis' max tick does not equal to its ylim top.

It doesn't feel like a bug, but it could be a behaviour that is nice to have, for example, when I need to match the grid lines for both axes manually by making sure that the chart actually shows the same number of ticks on both axes. At the moment RHS axis has 8 ticks but the chart only shows 7 of them by default. You can fix this with set_ybound(upper=...) but it's just a little inconvenient.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

x = [x + 0.5 for x in range(10)]
z = [(y+0.0)/10-0.004 for y in range(10)]
df1 = pd.DataFrame({'x': x})
df2 = pd.DataFrame({'z': z})

fig, ax1 = plt.subplots()
# df1.plot(ax=ax1)
ax1.plot(df1)

ax2= ax.twinx()
# df2.plot(ax=ax2, c='r')
ax2.plot(df2, c='r')

# uncommet this line below to set bounds explicitly which fixes this.
# ax2.set_ybound(upper=1.2)

print('ax1 ticks', ax.get_yticks())
print('ax2 ticks', ax2.get_yticks())

print('ax1 ybound', ax.get_ybound())
print('ax2 ybound', ax2.get_ybound()) # this shows the issue
print('ax2 ylim', ax2.get_ylim()) # this shows the issue

Output prints, Note: ax2's ylim & ybound max value are both 1 rather than 1.2, which is the max of its ticks:

('ax1 ticks', array([  0.,   2.,   4.,   6.,   8.,  10.]))
('ax2 ticks', array([-0.2,  0. ,  0.2,  0.4,  0.6,  0.8,  1. ,  1.2]))
('ax1 ybound', (0.0, 10.0))
('ax2 ybound', (-0.20000000000000001, 1.0000000000000002))
('ax2 ylim', (-0.20000000000000001, 1.0000000000000002))

Screenshot:

so

Activity

  1. added this to the milestone on Nov 25, 2015
  2. tacaswell commented on Nov 25, 2015

    @tacaswell
    Member

    I do not really understand either this issue or the SO question.

    Can you provide an example which does not go through pandas plotting?

  3. esvhd commented on Nov 25, 2015

    @esvhd
    ContributorAuthor

    Updated code above to use ax.plot instead of DataFrame.plot.

    Managed to upload the chart. Note that the RHS axis (variable ax2 in code) upper bound is at 1.0, but get_ticks() shows array([-0.2, 0. , 0.2, 0.4, 0.6, 0.8, 1. , 1.2]), question is why the upper bound isn't 1.2 by default, as suggested by the maximum tick value?

    This can be inconvenient sometimes. For example, one way to align the grid lines from both axes is to make sure both axes have the same number of ticks. (Welcome other suggestions!) The no. of ticks for RHS in the chart displayed do not match len(ax2.get_yticks()), which makes it a little inconvenient when determine what should be the common number of ticks for both axes.

    Hope this helps to clarify. Thanks.

  4. tacaswell commented on Nov 25, 2015

    @tacaswell
    Member

    So the minimal example is:

    x = [x + 0.5 for x in range(10)]
    z = [(y+0.0)/10-0.004 for y in range(10)]
    fig, ax = plt.subplots()
    ax2 = ax.twinx()
    
    ax.plot(x)
    ax2.plot(z, c='r')
    
    ax.grid(True, axis='y')
    ax2.grid(True, axis='y')

    get_yticks falls back to calling ax2.yaxis.major.locator() which asks the major locator instance where to put ticks. The way this is used internally in the library, this call is allowed to return extra locations (that may not be visible on the graph).

    The way that mpl is implemented underneath the tick locators, the tick formatters, and the axis limits are implemented independently (and that is definitely a feature).

  5. esvhd commented on Nov 25, 2015

    @esvhd
    ContributorAuthor

    Thanks for the explanation. What's the benefit of allowing ax2.yaxis.major.locator() to return extra locations that may not be visible on the graph?

    Also when you say that it is a feature to implement tick locator/formatter/axis limits independently, what are the benefits to do so? Just trying to understand the essence of its design.

    Appreciate it!

  6. WeatherGod commented on Nov 30, 2015

    @WeatherGod
    Member

    The primary benefit, IIRC, is to better handle situations involving
    floating point (im-)precision (i.e., by having extra ticks available in
    case one of them may actually be desirable).

    On Wed, Nov 25, 2015 at 5:47 PM, esvhd notifications@github.com wrote:

    Thanks for the explanation. When you say that it is a feature to implement
    tick locator/formatter/axis limits independently, what are the benefits to
    do so? Just trying to understand the essence of its design. Appreciate it!

    —
    Reply to this email directly or view it on GitHub
    #5560 (comment)
    .

  7. efiring commented on Jan 26, 2018

    @efiring
    Member

    If I understand the comments correctly, this can be closed now. If I have misunderstood, please reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions