I created a plot that has the same x and y limits, same scale for x and y ticks, hence guaranteeing the actual plot is perfectly square. Even with a legend included, the code below seems to keep the static plot (sp object) itself perfectly square even when the window in which it is positioned is rescaled:
library(ggplot2) library(RColorBrewer) set.seed(1) x = abs(rnorm(30)) y = abs(rnorm(30)) value = runif(30, 1, 30) myData <- data.frame(x=x, y=y, value=value) cutList = c(5, 10, 15, 20, 25) purples <- brewer.pal(length(cutList)+1, "Purples") myData$valueColor <- cut(myData$value, breaks=c(0, cutList, 30), labels=rev(purples)) sp <- ggplot(myData, aes(x=x, y=y, fill=valueColor)) + geom_polygon(stat="identity") + scale_fill_manual(labels = as.character(c(0, cutList)), values = levels(myData$valueColor), name = "Value") + coord_fixed(xlim = c(0, 2.5), ylim = c(0, 2.5))
However, I am now attempting to transfer this static plot (sp) into an interactive plot (ip) through ggplotly() that can be used in a Shiny app. I notice now that the interactive plot (ip) is no longer square-shaped. The MWE to show this is below:
ui.R
library(shinydashboard) library(shiny) library(plotly) library(ggplot2) library(RColorBrewer) sidebar <- dashboardSidebar( width = 180, hr(), sidebarMenu(id="tabs", menuItem("Example plot", tabName="exPlot", selected=TRUE) ) ) body <- dashboardBody( tabItems( tabItem(tabName = "exPlot", fluidRow( column(width = 8, box(width = NULL, plotlyOutput("exPlot"), collapsible = FALSE, background = "black", title = "Example plot", status = "primary", solidHeader = TRUE)))))) dashboardPage( dashboardHeader(title = "Title", titleWidth = 180), sidebar, body )
server.R
library(shinydashboard) library(shiny) library(plotly) library(ggplot2) library(RColorBrewer) set.seed(1) x = abs(rnorm(30)) y = abs(rnorm(30)) value = runif(30, 1, 30) myData <- data.frame(x=x, y=y, value=value) cutList = c(5, 10, 15, 20, 25) purples <- brewer.pal(length(cutList)+1, "Purples") myData$valueColor <- cut(myData$value, breaks=c(0, cutList, 30), labels=rev(purples)) # Static plot sp <- ggplot(myData, aes(x=x, y=y, fill=valueColor)) + geom_polygon(stat="identity") + scale_fill_manual(labels = as.character(c(0, cutList)), values = levels(myData$valueColor), name = "Value") + coord_fixed(xlim = c(0, 2.5), ylim = c(0, 2.5)) # Interactive plot ip <- ggplotly(sp, height = 400) shinyServer(function(input, output, session){ output$exPlot <- renderPlotly({ ip }) })
It seems there may not be a built-in/clear solution at this time (Keep aspect ratio when using ggplotly). I have also read about a HTMLwidget.resize object that might help solve a problem like this (https://github.com/ropensci/plotly/pull/223/files#r47425101), but I was unsuccessful determining how to apply such syntax to the current problem.
Any advice would be appreciated!
1 Answers
Answers 1
I tried playing with fixed axis ratio to no avail.
Setting the plot margins to create a square plot worked for me.
The plot is kept square even when the axis range changes.
When the axis ratio should be identical (i.e. the units are square but the plot is not), one would need to adjust the code a little bit (answer will be updated soon).
library(ggplot2) library(RColorBrewer) set.seed(1) x = abs(rnorm(30)) y = abs(rnorm(30)) value = runif(30, 1, 30) myData <- data.frame(x=x, y=y, value=value) cutList = c(5, 10, 15, 20, 25) purples <- brewer.pal(length(cutList)+1, "Purples") myData$valueColor <- cut(myData$value, breaks=c(0, cutList, 30), labels=rev(purples)) sp <- ggplot(myData, aes(x=x, y=y, fill=valueColor)) + geom_polygon(stat="identity") + scale_fill_manual(labels = as.character(c(0, cutList)), values = levels(myData$valueColor), name = "Value") + coord_fixed(xlim = c(0, 2.5), ylim = c(0, 2.5)) sp #set the height and width of the plot (including legends, etc.) height <- 500 width <- 500 ip <- ggplotly(sp, height = height, width = width) #distance of legend margin_layout <- 100 #minimal distance from the borders margin_min <- 50 #calculate the available size for the plot itself available_width <- width - margin_min - margin_layout available_height <- height - 2 * margin_min if (available_width > available_height) { available_width <- available_height } else { available_height <- available_width } #adjust the plot margins margin <- list(b=(height - available_height) / 2, t=(height - available_height) / 2, l=(width - available_width) / 2 - (margin_layout - margin_min), r=(width - available_width) / 2 + (margin_layout - margin_min)) ip <- layout(ip, margin=margin) ip
0 comments:
Post a Comment