plotly / plotly.R

An interactive graphing library for R
https://plotly-r.com
Other
2.56k stars 626 forks source link

Top and Bottom plots seem to have less spacing when using `subplot` in `plotly` #2378

Open mayank7j-shell opened 2 months ago

mayank7j-shell commented 2 months ago

Description:

When attempting to display multiple histograms using subplot from the plotly package, the plots in the top row and bottom row appear with less spacing, making them difficult to analyze. This issue is primarily reproducible when there are large number of visualizations to plot together.

Here is a minimal reprex for the same:

# Load necessary libraries
library(ggplot2)
library(plotly)

# set seed for reproducibility
set.seed(123)

# simulate a dataset
simulateDataset <- function(numRows = 100, numCols = 40) {
  data <- data.frame(matrix(nrow = numRows, ncol = numCols))

  for (i in 1:numCols) {
    if (i %% 2 == 0) {
      data[[i]] <- rnorm(numRows, mean = 50, sd = 10)  # Normal distribution
    } else {
      data[[i]] <- rexp(numRows, rate = 0.1)           # Exponential distribution
    }
  }

  names(data) <- paste0("Var", 1:numCols)
  return(data)
}

# simulate the data
df <- simulateDataset(numRows = 100, numCols = 45)

# create histograms and convert to plotly
plotList <- lapply(names(df), function(colName) {
  if (is.numeric(df[[colName]])) {
    p <- ggplot(df, aes(x = .data[[colName]])) + 
      geom_histogram(binwidth = 0.5, fill = 'grey', color = 'black')

    ggplotly(p)
  }
})

# define number of rows based on number of plots in each row
numberOfRows <- ceiling(length(plotList) / 3)

# display all plots together using subplot
subplot(plotList, nrows = numberOfRows, margin = 0.05, titleX = TRUE, titleY = TRUE)

Expected Behavior: Each histogram should have equal margins, with appropriate spacing and labels visible.

Screenshots

image

image

image

juliendiot42 commented 2 months ago

Hello,

I had the same problem and used this work around that may help people looking at this issue.

margin <- c(0.05, # left
            0.05, # right
            0.05, # top
            0.05) # bottom

heights = rep(1/numberOfRows, numberOfRows)
heights[1] <- heights[1] - margin[3]
heights[numberOfRows] <- heights[numberOfRows] - margin[4]
# heights <- heights + sum(margin[3:4]) / numberOfRows

numberOfCols <- ceiling(length(plotList) / numberOfRows)
widths = rep(1/numberOfCols, numberOfCols)
widths[1] <- widths[1] - margin[1]
widths[numberOfCols] <- widths[numberOfCols] - margin[2]
widths <- widths + sum(margin[1:2]) / numberOfCols

# display all plots together using subplot
subplot(plotList, nrows = numberOfRows, margin = margin, heights = heights, widths = widths, titleX = TRUE, titleY = TRUE)

the plots in the top row and bottom row appear with less spacing

I think the plots on the 1st and last row have more spaces than the other (cf. subplots.R) because the corresponding margins are not removed from their start/end coordinates. The suggested workaround will remove the margins spaces from their default allocated heights so all plots can have the same apparent size.

However doing that will lead to a total heights < 1 and in this case, the plots are centered So we end up with blank spaces at the top/bottom/left/right (it more or less force the top/left and bottom/right margins to the fist and last plots). This could be fine but to avoid that, the workaround add back the missing space evenly to all the plots (with your example, it works for the columns width but not for the rows heights, where this issue #2377 seems to occur...).

The workaround is not perfect though, especially if the margins are bigger than 1/numberOfRows or 1/numberOfCols the heights/width will be negative and will not be accepted by subplot().

Best regards, JD