tl;博士版本: 对于多面情节,我需要一种方法来
我目前正在构建一个 Shiny 应用程序,用于对各种数据集执行基本的探索性数据分析。我正在使用 ggplot2 和 plotly 来为不同的因素创建直方图。但是,当涉及到在 x 轴上显示长因子名称时,我遇到了一个问题。我尝试旋转标签以使它们更合适,但 plotly 似乎没有为它们分配足够的垂直空间,导致标签与绘图区域相交。这是一个屏幕截图,可以更好地说明我的问题:
所以我的问题是:
也许我问错了问题。完全手动弄乱绘图尺寸是个坏主意吗?我应该尝试其他方法吗?
另外,我注意到在某些情况下绘图区域变得非常小。 所以这是一个额外的问题:我怎样才能估计整个地块需要的大小,这样我就可以动态地缩放总高度,这样就不会被切断。
下面是一个最小的工作示例,其中包含来自
synthpop
包的虚拟数据:
library(shiny)
library(tidyverse)
library(plotly)
library(synthpop) # for example data
# generate example data frame
data <- synthpop::SD2011 |>
select(where(is.factor)) |>
slice(1:6)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(),
mainPanel(
plotlyOutput("hist_plot")
)
)
)
server <- function(input, output) {
hist_plot <- reactive({
data |>
pivot_longer(cols=everything(), names_to = "key", values_to = "value") |>
ggplot(aes(x=value)) +
geom_bar() +
facet_wrap(~key, nrow = 2, scales = "free_x") +
theme(
axis.text.x = element_text(angle = 90))
})
output$hist_plot <- renderPlotly({
req(hist_plot)
ggplotly(hist_plot())
})
}
shinyApp(ui = ui, server = server)
以下是我尝试/考虑过的一些事情:
renderPlot()
。然而,这会使绘图在应用程序中显得模糊,并且它有自己的缩放和重叠问题。plotlyOutput("hist_plot", height = "1000px")
。当我知道我需要的总大小时,这在一定程度上解决了问题,但它也增加了绘图区域和标签的大小。理想情况下,我们应该能够独立控制整体图表大小和绘图的大小。编辑:添加 tl:dr 部分
因为我不知道你的应用程序中还有什么,我怀疑这是一个“一次性”答案。在你完成它之后,如果它不适合你,请告诉我你的想法。我确定这 not 完美。有太多的静态尺寸无法发生。
一些需要注意的事情,与这个答案相关
ggplot
带到 plotly
时,它做了一些矫揉造作,但预料之中的事情plotly.annotations
plotly.shapes
fixer()
功能yanchor
y
位置大部分代码没有从您问题中的代码更改。在代码中查找我的注释以注意更改。如果您有任何疑问,我只是发表评论。
library(shiny)
library(tidyverse)
library(plotly)
library(synthpop) # for example data
# generate example data frame
data <- synthpop::SD2011 |>
select(where(is.factor)) |>
slice(1:6)
fixer <- function(pt) { # <--- I added
rg <- pt$x$layout$yaxis2$domain[2] # graph size based on domain
lapply(1:length(pt$x$layout$shapes), function(i) { # modify shapes
if(isTRUE(pt$x$layout$shapes[[i]]$yanchor == rg)) { # isTRUE for errors
pt$x$layout$shapes[[i]]$yanchor <<- 2.5 * rg # move grey squares up
}
})
lapply(1:length(pt$x$layout$annotations), function(j) { # modify annotations
if(isTRUE(round(pt$x$layout$annotations[[j]]$y, 6) == round(rg, 6))) { ## isTRUE for errors
pt$x$layout$annotations[[j]]$y <<- 2.5 * rg # move facet labels up
}
})
pt$x$layout$yaxis2$domain <- c(1.5 * rg, 2.5 * rg) # modify plot positions
pt
}
ui <- fluidPage(
tags$head( # <--- I added
tags$style(HTML( # dynamic x-axis labels' size; dynamic plot height
".xaxislayer-above text{
font-size: calc(6px + 6 * ((100vw - 300px) / (1600 - 300))) !important;
}
#hist_plot{
height: 75vh !important;
}"))
),
sidebarLayout(
sidebarPanel(),
mainPanel(
plotlyOutput("hist_plot")
)
)
)
server <- function(input, output) {
hist_plot <- reactive({
data |>
pivot_longer(cols=everything(), names_to = "key", values_to = "value") |>
ggplot(aes(x=value)) +
geom_bar() +
facet_wrap(~key, nrow = 2, scales = "free_x") +
theme(
axis.text.x = element_text(angle = 90))
})
output$hist_plot <- renderPlotly({
req(hist_plot)
ggplotly(hist_plot()) %>%
layout(margin = list(b = 100)) %>% fixer() # <--- I added
})
}
shinyApp(ui = ui, server = server)