Hi, I met the same error, and came here after googling.
For future reference, below I write the reason and workarounds I found for my case.
In my case, the reason is I gave multiple elements in a vector as an argument of xlab
(and ylab
) of ggplot2
.
ggplot2
does not complain anything and silently processes successfully the first element in the vector as the label as if a single value is given as a label, whereas ggplotly
dies with this Error in if: the condition has length > 1
error which is originated in gg2list
.
My first quick workaround is to add unique()
to the arguments of xlab
and ylab
. Also in my case the labels are indeed coming from input values, so I can simply replace them to the input values.
A reprex is as below. I also put my two ways of fix below by the ways as described above.
library(shiny)
library(ggplot2)
library(plotly)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# UI Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
ui <- fluidPage(
selectInput("label_x", "My label for x-axis", c('my own1', 'my own2')),
h4("Plot by ggplotly"),
# plotlyOutput("ggplotly_ok_wo_xlab"),
plotlyOutput("ggplotly_notok"),
# plotlyOutput("ggplotly_ok_way1"),
# plotlyOutput("ggplotly_ok_way2"),
h4("Plot by ggplot"),
plotOutput("ggplot")
)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# Server Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
server <- function(input, output, session) {
# Construction of ggplot object g is the same in both output$ggplot and output$ggplotly_notok.
# Still, ggplot is ok whereas ggplotly_notok dies with message 'Error in if: the condition has length > 1'.
output$ggplot <- renderPlot({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
# not necessarily the same length as the n_row of data:
# xlabs_my <- rep(label_x, 3)
# indeed `ggplot` silently picks up the first element even when different values are given:
# xlabs_my <- c('my1', 'my 2')
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlabs_my))
g
})
output$ggplotly_ok_way1 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
output$ggplotly_ok_way2 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
# xlabs_my <- rep(label_x, dim(faithful)[1])
xlab_my <- paste0('(which is taken directly from input): ', label_x)
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlab_my))
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
# Construction of ggplot object g is the same in both output$ggplot and output$ggplotly_notok.
# Still, ggplot is ok whereas ggplotly_notok dies with message 'Error in if: the condition has length > 1'.
output$ggplotly_notok <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
# output$ggplotly_ok_wo_xlab, which is without the part of xlab addition, works fine.
output$ggplotly_ok_wo_xlab <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
# g <- g +
# # xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
# print(ggplot2::last_plot())
ggplotly(g)
})
# stat_density_2d(aes(fill = ..level..), geom = "polygon") +
# Warning: The dot-dot notation (`..level..`) was deprecated in ggplot2 3.4.0.
# ℹ Please use `after_stat(level)` instead.
# ℹ The deprecated feature was likely used in the ggplot2 package.
# Please report the issue at <https://github.com/tidyverse/ggplot2/issues>.
}
# Run the application
shinyApp(ui = ui, server = server)
- The error message with the above
app.R
Warning: Error in if: the condition has length > 1
104: gg2list
103: ggplotly.ggplot
101: renderPlotly [<mytopdir>/app.R#113]
100: func
97: shinyRenderWidget
96: func
83: renderFunc
82: output$ggplotly_notok
1: shiny::runApp
- Workaround 1, use
unique()
library(shiny)
library(ggplot2)
library(plotly)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# UI Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
ui <- fluidPage(
selectInput("label_x", "My label for x-axis", c('my own1', 'my own2')),
h4("Plot by ggplotly"),
# plotlyOutput("ggplotly_notok"),
plotlyOutput("ggplotly_ok_way1"),
# plotlyOutput("ggplotly_ok_way2"),
h4("Plot by ggplot"),
plotOutput("ggplot")
)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# Server Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
server <- function(input, output, session) {
output$ggplot <- renderPlot({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
# not necessarily the same length as the n_row of data:
# xlabs_my <- rep(label_x, 3)
# indeed `ggplot` silently picks up the first element even when different values are given:
# xlabs_my <- c('my1', 'my 2')
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlabs_my))
g
})
output$ggplotly_ok_way1 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
output$ggplotly_ok_way2 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
# xlabs_my <- rep(label_x, dim(faithful)[1])
xlab_my <- paste0('(which is taken directly from input): ', label_x)
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlab_my))
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
output$ggplotly_notok <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
# stat_density_2d(aes(fill = ..level..), geom = "polygon") +
# Warning: The dot-dot notation (`..level..`) was deprecated in ggplot2 3.4.0.
# ℹ Please use `after_stat(level)` instead.
# ℹ The deprecated feature was likely used in the ggplot2 package.
# Please report the issue at <https://github.com/tidyverse/ggplot2/issues>.
}
# Run the application
shinyApp(ui = ui, server = server)
- Workaround 2, taken from input
library(shiny)
library(ggplot2)
library(plotly)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# UI Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
ui <- fluidPage(
selectInput("label_x", "My label for x-axis", c('my own1', 'my own2')),
h4("Plot by ggplotly"),
# plotlyOutput("ggplotly_notok"),
# plotlyOutput("ggplotly_ok_way1"),
plotlyOutput("ggplotly_ok_way2"),
h4("Plot by ggplot"),
plotOutput("ggplot")
)
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
# Server Side ----
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
server <- function(input, output, session) {
output$ggplot <- renderPlot({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
# not necessarily the same length as the n_row of data:
# xlabs_my <- rep(label_x, 3)
# indeed `ggplot` silently picks up the first element even when different values are given:
# xlabs_my <- c('my1', 'my 2')
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlabs_my))
g
})
output$ggplotly_ok_way1 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
output$ggplotly_ok_way2 <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
# xlabs_my <- rep(label_x, dim(faithful)[1])
xlab_my <- paste0('(which is taken directly from input): ', label_x)
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
xlab(paste0('my xlab is: ', xlab_my))
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
# xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
output$ggplotly_notok <- renderPlotly({
label_x <- input$label_x
# dim(faithful)
# [1] 272 2
xlabs_my <- rep(label_x, dim(faithful)[1])
g <- ggplot(faithful, aes(x = eruptions, y = waiting)) +
stat_density_2d(aes(fill = after_stat(level)), geom = "polygon") +
xlim(1, 6) + ylim(40, 100)
g <- g +
# xlab(unique(paste0('my xlab is: ', xlabs_my)))
xlab(paste0('my xlab is: ', xlabs_my))
ggplotly(g)
})
# stat_density_2d(aes(fill = ..level..), geom = "polygon") +
# Warning: The dot-dot notation (`..level..`) was deprecated in ggplot2 3.4.0.
# ℹ Please use `after_stat(level)` instead.
# ℹ The deprecated feature was likely used in the ggplot2 package.
# Please report the issue at <https://github.com/tidyverse/ggplot2/issues>.
}
# Run the application
shinyApp(ui = ui, server = server)
> library(shiny)
>
> library(ggplot2)
> library(plotly)
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
> sessionInfo()
R version 4.3.2 (2023-10-31)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Sonoma 14.4.1
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: Asia/Tokyo
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] plotly_4.10.4 ggplot2_3.5.0 shiny_1.8.0
loaded via a namespace (and not attached):
[1] jsonlite_1.8.8 gtable_0.3.4 dplyr_1.1.4 compiler_4.3.2 promises_1.2.1 tidyselect_1.2.0
[7] Rcpp_1.0.12 tidyr_1.3.1 later_1.3.2 scales_1.3.0 fastmap_1.1.1 mime_0.12
[13] R6_2.5.1 labeling_0.4.3 generics_0.1.3 isoband_0.2.7 htmlwidgets_1.6.4 MASS_7.3-60.0.1
[19] tibble_3.2.1 munsell_0.5.0 pillar_1.9.0 rlang_1.1.3 utf8_1.2.4 httpuv_1.6.14
[25] lazyeval_0.2.2 viridisLite_0.4.2 cli_3.6.2 withr_3.0.0 magrittr_2.0.3 digest_0.6.34
[31] grid_4.3.2 rstudioapi_0.15.0 xtable_1.8-4 lifecycle_1.0.4 vctrs_0.6.5 data.table_1.15.0
[37] glue_1.7.0 farver_2.1.1 fansi_1.0.6 colorspace_2.1-0 purrr_1.0.2 httr_1.4.7
[43] tools_4.3.2 pkgconfig_2.0.3 ellipsis_0.3.2 htmltools_0.5.7
>