Skip to content

Better secondary axis tick positioning #3581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

Ilia-Kosenkov
Copy link

This PR suggests a solution that addresses issue #3576.
When plotting the secondary axis, tick positions of the secondary should be transformed to the range of the primary axis (AxisSecondary$break_info()). To achieve this, a grid (old_range) is generated (of the size AxisSecondary$detail, defaulted to 1000). This grid is then transformed to the secondary axis scale (named full_range). Each tick of the secondary axis is transformed to the primary's scale by finding the index of the closest value in the full_range (index <- which.min(abs(full_range - x))) and adopting old_range[index] as tick position in the primary axis scale.

It is easy to understand that if full_range does not contain values equal to the secondary axis ticks, transformation is not accurate and the quality of this transformation depends on the grid size. This is observed in #3576, when duplicated axis (dup_axis) cannot properly position its ticks.

A simple alternative solution is to introduce linear interpolation. Instead of using the closest grid value, it is better to use two grid values and interpolate in between to increase the quality of the transformation. This works exceptionally well in the case of linear transformations of the secondary axis, including duplicated axes (dup_axis).

The method works well for different combinations of primary/secondary transformations, including when one axis is monotonically increasing while another is decreasing. There are no checks for boundary cases, i.e. when ticks are found at the edges of the grid, which I assume never happens.

@paleolimbot
Copy link
Member

Hi @Ilia-Kosenkov - I'm linking this to #3576 so that reviewers can read up on the back-story.

My two cents is that while linear interpolation is clearly a more accurate than a 1000-point nearest-neighbour approximation, I wonder if the scales package is a better place to implement this...something like trans_fun(fun, limits) that abstracts the details of transformation away from ggplot code.

@Ilia-Kosenkov
Copy link
Author

Hi @paleolimbot.
I came up with such a solution while looking through the ggplot2's internal code related to #3576.
Now that you know the source of this problem, you can probably find something more reliable & appropriate than this simple interpolation.

I find secondary axes extremely useful and believe that ggplot2 will benefit from better secondary ticks.

Also, as far as I understand, the test data/template plots were generated with poorly positioned secondary ticks, so I am not sure how to properly test my changes. It seems that all secondary axis-related tests have failed.
It can be useful to implement a test similar to what I showed in #3576 - i.e. duplicating an axis and comparing tick positions (in units) on both sides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants