Skip to content

Add support for alternative axis sides in ggplotly #813

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
wants to merge 21 commits into from
Closed

Add support for alternative axis sides in ggplotly #813

wants to merge 21 commits into from

Conversation

alanocallaghan
Copy link
Contributor

This is a fairly straightforward edit and shouldn't break any existing functionality. It just adds support for the new axis locations (top and right) in ggplot2 2.2.0 which already have support in plotly.js

@talgalili
Copy link
Contributor

Great - thanks for your work @alanocallaghan

@alanocallaghan
Copy link
Contributor Author

Cheers Tal

Addresses #808

@cpsievert
Copy link
Collaborator

Thanks @alanocallaghan, this is a nice start 🍻 , but it will have to be generalized if we want it to work with facets.

To do so, I think you can essentially copy the same logic over to the axis object generation step

And before I merge anything, it'd be great to have some tests!

@alanocallaghan
Copy link
Contributor Author

Thanks for getting back quickly. Moving the logic seems to work fine.

Regarding facets, some of the other new additions in ggplot 2.2.0 might also require small edits, but I've not tested any yet. Probably one to watch out for, though

Regarding tests, I've written simple tests that verify whether the position moves and ensure 1 trace

Cheers

@alanocallaghan
Copy link
Contributor Author

I should say that if you would like further tests or tests with more complex plots, just say the word

@cpsievert
Copy link
Collaborator

Nice work! More tests are always good...lets put a test with facets in there as well

@alanocallaghan
Copy link
Contributor Author

Unfortunately, the facet functionality technically works (http://i.imgur.com/s2PIqXA.png) but requires a bit more work...

@talgalili
Copy link
Contributor

Hi @cpsievert - any chance you'll give this a look?
Adding alternative location for the axis is a feature various people have asked for.

Thanks.

@alanocallaghan
Copy link
Contributor Author

I can pick this up again tonight and resolve the failing test and conflicts; it will still look awful with facets for the time being

@alanocallaghan
Copy link
Contributor Author

@cpsievert or any others

The test errors are now not related to my PR (they seem to be in the master branch). I can pull in the master when the current issue is resolved.

As for facet functionality, for the x axis on the top, I'm not sure of the logic needed to pad the facet "strip" (made by make_strip_rect) in order to show the axis in this position.

For the y axis, the position is a bit trickier. You need to move the axis from the leftmost plot to the rightmost plot... Not sure where the logic for this is found.

For both plots, you also need to move the axis label.

Any pointers on where to look would be great, the ggplotly code is quite dense as it's not split into many functions.

@alanocallaghan
Copy link
Contributor Author

alanocallaghan commented Feb 18, 2017

The parameter is axis anchoring, eg

layout(yaxis = list(anchor = "x2"))

@alanocallaghan
Copy link
Contributor Author

alanocallaghan commented Feb 21, 2017

Made some progress, but unfortunately the "annotation" x/y axis labels and striptext are difficult to move. I think the best way forward is to extend the axis ticks, via axisObj$ticklen, beyond the striptext. This also handles moving the tick text.

Related:

#510

@alanocallaghan
Copy link
Contributor Author

alanocallaghan commented Feb 21, 2017

I've managed to get this to work reasonable well for a few different facets, shown in these images (http://imgur.com/a/DYCDt). Will write some tests for these

@alanocallaghan
Copy link
Contributor Author

y axis labels are not the right way up...

@alanocallaghan
Copy link
Contributor Author

Should be good to go once I write tests for all of the changes made

@talgalili
Copy link
Contributor

Thank you for all your great work @alanocallaghan !

@alanocallaghan
Copy link
Contributor Author

Tests took a while to get right (can't run them locally), should be golden now

@alanocallaghan
Copy link
Contributor Author

@cpsievert can you have a look whenever you have time? Thanks

@ck37
Copy link

ck37 commented Mar 2, 2017

Really interested in this patch. When I use it to move the x-axis to the top (to avoid the horizontal legend overlapping bug) the x-axis overlaps with the title. Is there any way to fix that?

Code:

    p = plot_ly(ellipse, x = ~x, y = ~y, split = ~source) %>%
      layout(title = "Archeological Geochemistry",
             xaxis = list(title = names(elements)[elements == input$element1],
                          side = "top"),
             yaxis = list(title = names(elements)[elements == input$element2]),
             legend = list(orientation = "h"))

Screenshot: http://imgur.com/a/unwwf

@alanocallaghan
Copy link
Contributor Author

Good spot, here's a reprex equivalent with mtcars:

p <- plot_ly(mtcars, x = ~cyl, y=~mpg, color =~gear) %>%
    layout(title = "Archeological Geochemistry",
         xaxis = list(title = "X Axis Title",
                      side = "top"),
         yaxis = list(title = "Y Axis Title"),
         legend = list(orientation = "h"),
         margin=list(t=100))

@alanocallaghan
Copy link
Contributor Author

alanocallaghan commented Mar 2, 2017

This is actually related to plotly itself, while this PR only touches ggplotly. @ck37 you may be best served looking at annotations https://plot.ly/r/text-and-annotations/

R/ggplotly.R Outdated

## Move axis and change anchor if necessary
if (has_facet(plot)) {
if (non_default_side) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where possible, I prefer:

if (x && y) {
}

to

if (x) {
  if (y) {
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think I'd just thought the logic was going to be more complex

R/ggplotly.R Outdated
(unitConvert(stripText, "pixels", type) * 2.5)
if (nRows > 1) {
axisObj[["anchor"]] <- "y"
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there are multiple rows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the if statement is actually redundant, since it will always need to be anchored to the first row, whether there is more than one row or not


test_that("Axis position moves to right", {
p <- p + scale_y_continuous(position="right")

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The axis currently isn't shown because this PR hasn't yet addressed the issue of adding space for axis ticks/text in the right margin (and removing from the left) as is done here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, thanks for the tip

@alanocallaghan
Copy link
Contributor Author

Thanks, I'll fix these and do more extensive checks tomorrow

@@ -599,7 +599,8 @@ gg2list <- function(p, width = NULL, height = NULL,
if (xy == "x") {
## Facet labels are always on top, so add tick length to move past them
axisObj[["ticklen"]] <- axisObj[["ticklen"]] +
(unitConvert(stripText, "pixels", type) * 2.5)
(unitConvert(stripText, "pixels", type) * 3)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a magic number. I don't think ticklen can vary dynamically so it has to be large enough to accomodate large and small window sizes. It'll be too long for small window sizes but if it's extreme the user can adjust it using p %>% layout(xaxis=list(ticklen=10), xaxis2=list(ticklen=10), ...).

I'll log an issue on the plotly.js github to see if it would be possible to have ticklen optionally be a proportion of the plot rather than strictly pixels, but otherwise it's a necessary evil

@alanocallaghan
Copy link
Contributor Author

The failure is due to package semver... Going to try re-running to see if it still fails

@talgalili
Copy link
Contributor

Hi @alanocallaghan
Any chance this could be resolved?
(once done, heatmaply would be able to support left dendrograms with plot_method="ggplot", which would be a good thing, I believe)

Thanks.

@alanocallaghan
Copy link
Contributor Author

The fail on R-devel seems to be down to Rserve connection to the plotly servers. Regarding this functionality, I can't do much more while #1458 is still open so it's up to @cpsievert where to go from here, though I imagine he's busy with PlotCon around now

@talgalili
Copy link
Contributor

Hi @alanocallaghan Just to be sure - I can't seem to find issue #1458, which issue did you mean?

@alanocallaghan
Copy link
Contributor Author

Sorry: plotly/plotly.js#1458

@cpsievert
Copy link
Collaborator

Don't worry about the test failures @alanocallaghan. I'll have a closer look here next week

@cpsievert
Copy link
Collaborator

@alanocallaghan Just FYI, #929 should supersede this, but I may use some of your tests -- #929 is a refactoring of the labs() framework which should fix/add support for a bunch of things. Alternative axes are coupled with that logic, so I'll handle it over there.

@plotly plotly deleted a comment from KeeonTabrizi Feb 27, 2019
@alanocallaghan
Copy link
Contributor Author

Closing as superseded

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.

4 participants