【问题标题】:Shiny: unwanted space added by plotOutput() and/or renderPlot()闪亮:plotOutput() 和/或 renderPlot() 添加的不需要的空间
【发布时间】:2017-12-07 19:42:53
【问题描述】:

plotOutput 或 renderPlot 似乎在情节周围添加了一堆额外的空白。我在绘图和布局列中添加了背景颜色来说明这一点。从本质上讲,我想完全摆脱这个空白,只留下蓝色区域,然后它应该与列的左侧对齐。

我知道这可以使用 width 参数进行调整,但是将其设置为 100% 或 auto 似乎无法正常工作。

谢谢!

library(shiny)
library(ggplot2)

# Create sample data
animals <- as.data.frame(
  table(Species =
          c(rep("Moose", sample(1:100, 1)),
            rep("Frog", sample(1:100, 1)),
            rep("Dragonfly", sample(1:100, 1))
          )))

server <- function(input, output) {

  output$pieChart <- renderPlot({

    # Create pie chart
    ggplot(animals, aes(x = "", y = Freq, fill = Species)) +
      geom_bar(width = 1, stat = "identity") +
      coord_polar("y", start=0) +
      theme(plot.background = element_rect(fill = "lightblue"))
  })
}

ui <- fluidPage(

  fluidRow(
    column(4, 
           style = "background-color:lightgreen",
           align = "left",
           HTML("filler<br>"),
           plotOutput("pieChart")
    )
  )
)

shinyApp(ui = ui, server = server)

【问题讨论】:

  • 嗨,几年后我遇到了几乎同样的问题 - 我想知道你是否设法找到了更优雅的解决方案?
  • 已经有一段时间了,但我相信我选择了下面 Brian 的解决方案

标签: r ggplot2 shiny


【解决方案1】:

空间是由网格布局引擎添加的,而不是任何闪亮的东西。 Grid 添加了空白,因为 ggplot 要求它保持绘图的纵横比,以确保圆圈是圆形的。

您可以通过以下方式查看。首先,让我们以常规方式绘制绘图,但我们先手动转换为 grob。

g <- ggplot(animals, aes(x = "", y = Freq, fill = Species)) +
  geom_bar(width = 1, stat = "identity") +
  coord_polar("y", start=0) +
  theme(plot.background = element_rect(fill = "lightblue"))

library(grid)
grob <- ggplotGrob(g)
grid.newpage()
grid.draw(grob)

这将在侧面或上方/下方生成带有空白的绘图,具体取决于封闭窗口的形状:

现在让我们关闭纵横比强制并再次绘图:

grob$respect <- FALSE # this switches of the fixed aspect ratio
grid.newpage()
grid.draw(grob)

现在没有空白了,而且圆也不是圆的。

您必须将绘图放入一个封闭的容器中,该容器可以在右侧和底部提供必要的空白。 grid 如果您愿意为绘图提供固定大小,则可以使用grid 将绘图放入一个侧面和底部有空白空间的表格中:

library(grid)
library(gtable)
# need to play around to find numbers that work
plotwidth = unit(6.1, "inch")
plotheight = unit(5, "inch")

grob <- ggplotGrob(g)
mat <- matrix(list(grob, nullGrob(), nullGrob(), nullGrob()), nrow = 2)
widths <- unit(c(1, 1), "null")
widths[1] <- plotwidth
heights <- unit(c(1, 1), "null")
heights[1] <- plotheight
gm <- gtable_matrix(NULL, mat, widths, heights)
grid.newpage()
grid.draw(gm)

这种方法的缺点是现在,如果绘图窗口太小,绘图将不会调整大小而是会被截断:

我不确定如何将绘图缩放到仍适合窗口的最大尺寸。

【讨论】:

  • 谢谢!信息量很大。这为我提供了足够的理解来找出解决方案。
【解决方案2】:

我在地图上遇到了类似但不相同的问题。我知道我想要地图中的纵横比(对我来说正好是 1:1),就像你的饼图一样,我希望它尽可能多地占据响应列的宽度,改变高度因此。但是,我不希望它太大大,所以我添加了一条逻辑将其限制为 400 像素宽。

我的方法是绘制一个不可见的虚拟ggplot 对象,然后查询客户端会话以了解其大小。然后我可以将该大小作为显式参数传递给实际所需的绘图。

# you need to include `session` as a third argument here
server <- function(input, output, session) {

  # blank (plot for width) ----
  output$blank <- renderPlot({
    ggplot(data.frame(x = 1), aes(NA, NA)) + geom_blank() + theme_void()
  })

  blankwidth <- reactive({
          # this is the magic that makes it work
    bw <- session$clientData$output_blank_width
    if (bw > 400) 400 else bw
  })

  blankheight <- reactive({
    blankwidth() / 1.25
    # whatever aspect ratio you need
  })

  output$plotofinterest <- renderPlot({
    ggplot(iris[sample.int(150,50),], aes(1, fill = Species)) + 
      geom_bar() + coord_polar(theta = "y")
  }, height = blankheight, width = blankwidth)
     # this is the necessary bit
}

# ui.R

ui <- fluidPage(
  fluidRow(
    column(4,
           style = "background-color:lightgreen",
           plotOutput('blank', width = '100%', height = 0),
           plotOutput('plotofinterest', inline = T)
    ),
    column(8,
           style = "background-color:lightblue",
           HTML("filler")
    )
  )
)

shinyApp(ui, server)

如果你让窗口变窄,绘图会小于 400px 的上限,并且会占据整列。如果你把它变宽,右侧的绿地就会变大。我没有注意到绘制额外的绘图以从客户端获取此信息会导致性能大幅下降。即使您拖动窗口大小来玩它,它也会很快更新。

您确实需要弄清楚您希望它以什么纵横比绘制。 grid 会自动将Claus explained 之类的空白添加到不受限制的一对边距中,因此只需注意一下,直到它看起来不错。

【讨论】:

  • 为我工作!非常感谢
猜你喜欢
  • 2016-10-12
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 2014-10-15
  • 2018-07-01
  • 2021-09-26
相关资源
最近更新 更多