Skip to content

Enchance subplot()'s ability to handle pre-specified domain(s) #376

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
talgalili opened this issue Dec 29, 2015 · 9 comments
Closed

Enchance subplot()'s ability to handle pre-specified domain(s) #376

talgalili opened this issue Dec 29, 2015 · 9 comments

Comments

@talgalili
Copy link
Contributor

subplot seems the way to create a scatterplot with marginal histograms in plotly.

However, in order to have it work it needs to:

  1. share the same axes so that all figures will respond to zoom together
  2. we need control over each plots' width.

Example of how it should look like:

# Get some data
library(ggplot2 )
theme_set(theme_classic())
hist_top <- ggplot()+geom_histogram(aes(rnorm(100)))
empty <- ggplot()+geom_blank()
scatter <- ggplot()+geom_point(aes(rnorm(100), rnorm(100)))
hist_right <- ggplot()+geom_histogram(aes(rnorm(100)))+coord_flip()
library(gridExtra)
grid.arrange(hist_top, empty, scatter, hist_right, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

Which looks like this:

image

And this is how it actually looks like (which should be corrected):

# hide axis ticks and grid lines
eaxis <- list(
  showticklabels = FALSE,
  showgrid = FALSE,
  zeroline = FALSE
)

p_empty <- plot_ly(filename="r-docs/dendrogram") %>%
  # note that margin applies to entire plot, so we can
  # add it here to make tick labels more readable
  layout(margin = list(l = 200),
         xaxis = eaxis,
         yaxis = eaxis)

subplot(hist_top, p_empty, scatter, hist_right, nrows=2, margin = 0.01)

image

@cpsievert
Copy link
Collaborator

The shared axes issue is reported in #298. The coord_flip() issue will be fixed in #390.

As for controlling the widths/heights of subplots -- for now you'll have to plotly_build() the subplot and alter the domains by hand:

x <- rnorm(100)
y <- rnorm(100)
p1 <- plot_ly(x = x, type = "histogram")
p2 <- plotly_empty()
p3 <- plot_ly(x = x, y = y, mode = "markers") 
p4 <- plot_ly(y = y, type = "histogram")
s <- subplot(p1, p2, p3, p4, nrows = 2)
l <- plotly_build(s)

# alter heights/widths
l$layout$xaxis$domain <- c(0, 0.8)
l$layout$xaxis2$domain <- c(0.8, 1)
l$layout$xaxis3$domain <- c(0, 0.8)
l$layout$xaxis4$domain <- c(0.8, 1)
l$layout$yaxis$domain <- c(0.8, 1)
l$layout$yaxis2$domain <- c(0.8, 1)
l$layout$yaxis3$domain <- c(0, 0.8)
l$layout$yaxis4$domain <- c(0, 0.8)
# axis titles/ticks should go too
l$layout$xaxis$title <- NULL
l$layout$xaxis$showticklabels <- F
l$layout$yaxis4$title <- NULL
l$layout$yaxis4$showticklabels <- F

It'd be nice if subplot() would respect layout(p, xaxis = list(domain = c(0, 0.8)) regardless of which axis it actually ends up being in the subplot, but I wouldn't consider that a high priority for now.

@cpsievert cpsievert changed the title Allow subplot to share the same axis, respond together to zoom, and control each plots' width Enchance subplot()'s ability to handle pre-specified domain(s) Jan 14, 2016
@talgalili
Copy link
Contributor Author

Thanks @cpsievert - looking forward to updates on this.
Eventually being able to have this type of plot (scatterplot + marginal histograms), would be great.

With regards,
Tal

@talgalili
Copy link
Contributor Author

Hi @cpsievert - I see here another way of creating this plot:
https://plot.ly/~snawel/80/brand-choices-for-age-60/
Do you have a suggestion in which way is better (or if there would be a new function in the near future that would make it easier?)

Thanks.

@royr2
Copy link

royr2 commented Feb 9, 2016

@talgalili - Here's something you could try. It (sort of) emulates your grid.arrange()example. Instead of dealing with subplot() you could use layout() and specify domains for each axis.

Hopefully this helps while @cpsievert is working on a more practical solution.

x <- rnorm(1000)
y <- rchisq(1000, df = 5)

ds <- data.frame(x,y)

ds %>% 
  plot_ly(x = x, y = y, type = "scatter", mode = "markers", showlegend = F, opacity = 0.7, 
          marker = list(symbol = "circle-dot",
                        size = 8)) %>%   # First trace
  add_trace(y = y, type = "histogram", xaxis = "x2", orientation = "h") %>%  # Second trace; Note the use of "x2"
  add_trace(x = x, type = "histogram", yaxis = "y2") %>%  # Second trace; Note the use of "x2"

  layout(title = "Marginal Histograms using Multiple Axis",
         xaxis = list(title = "X variable",
                      domain = c(0,0.85),
                      range = c(-3,3), 
                      showgrid = TRUE),
         xaxis2 = list(title = "Y Histogram",
                       domain = c(0.85,1), 
                       zeroline = FALSE),
         yaxis = list(title = "Y variable",
                      range = c(0,30), 
                      domain = c(0,0.85),
                      showgrid = TRUE),
         yaxis2 = list(title = "X Histogram",
                       domain = c(0.85,1),
                       zeroline = FALSE))

@talgalili
Copy link
Contributor Author

Hi @royr2 - thank you for the code tip. I have a followup question:
I want to use add_trace and layout with the output of a ggplotly object. Sadly, in every variation I try I keep getting:

Error in FUN(X[[i]], ...) : 
  'options' must be a fully named list, or have no names (NULL)

Could you please show a similar example as you did, but using the output of the objects in my original question? (i.e.: hist_top, empty, scatter, hist_right)

Thanks!

Tal

@talgalili
Copy link
Contributor Author

Code for reproducing the error:

x <- rnorm(1000)
y <- rchisq(1000, df = 5)
ds <- data.frame(x,y)

p <- ds %>% qplot(x = x, y = y, data = .)
py <- ds %>% ggplot(aes(x=x)) + geom_histogram(binwidth=.5) 

  ggplotly(p) %>%   # First trace
  # add_trace(y = y, type = "histogram", xaxis = "x2", orientation = "h") %>%  # Second trace; Note the use of "x2"
  add_trace(py, xaxis = "x2", orientation = "h") %>%  # Second trace; Note the use of "x2"
  add_trace(x = x, type = "histogram", yaxis = "y2") %>%  # Second trace; Note the use of "x2"

  layout(title = "Marginal Histograms using Multiple Axis",
         xaxis = list(title = "X variable",
                      domain = c(0,0.85),
                      range = c(-3,3), 
                      showgrid = TRUE),
         xaxis2 = list(title = "Y Histogram",
                       domain = c(0.85,1), 
                       zeroline = FALSE),
         yaxis = list(title = "Y variable",
                      range = c(0,30), 
                      domain = c(0,0.85),
                      showgrid = TRUE),
         yaxis2 = list(title = "X Histogram",
                       domain = c(0.85,1),
                       zeroline = FALSE))

Output is:

Error in FUN(X[[i]], ...) : 
  'options' must be a fully named list, or have no names (NULL)

@talgalili
Copy link
Contributor Author

o.k., looking at this more, I see that my previous code wouldn't make sense. I see that add_trace takes a plotly object and adds another element to it (but it doesn't seem to allow the merging of two plotly objects).
Is there a way to merge two plotly objects into one layout?

If not then I guess the only way to get what I asked is (as the ticket says): "Enchance subplot()'s ability to handle pre-specified domain(s)"

This would be VERY useful for my work, so I hope this could get addressed.

Thanks,
Tal

@cpsievert
Copy link
Collaborator

There isn't any reason why subplot() couldn't support ggplot2 as well. Let's continue that discussion in #520

@cpsievert cpsievert mentioned this issue Mar 19, 2016
4 tasks
@cpsievert
Copy link
Collaborator

Fixed via dd9a3fa

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

No branches or pull requests

3 participants