Originally I asked this question about suppressing the whiskers on a boxplot made by ggboxplot
. (The expected way of setting a geom_boxplot
option was not available.) A nice solution appeared which suited the original question. However, the broader question to address is how to suppress whiskers on the boxplot but still retain access to the nice additions in ggpubr
, such as being able to automatically compute statistical test results and place these on a boxplot.
I tinkered with the solution from @Julian_Hn to get something like what I want. There are two issues that someone more knowledgeable might be able to help with, now that I've asked the broader question:
ggpar
and coord_cartesian
, with no effect. I might be lacking knowledge of how to use commands like ggplot_build
effectively.)Here's an example where I suppress whiskers and use stat_kruskal_test
to label the boxplot:
ggboxplot_whisker_opt <- function(...)
{
opts <- list(...) # Modification of original question solution to include the original labelled ggboxplot with whiskers and stat info added
# Check if user specified a whiskers arg and set options accordingly
if("whisker" %in% names(opts))
{
whisk <- opts$whisker
opts$whisker <- NULL
} else {
whisk <- TRUE
}
# Additional arguments that might need generalising so that other statistical tests can be used in other applications
if ("kruskal" %in% names(opts))
{ kruskal<-opts$kruskal
opts$kruskal <- NULL
opt.group <- opts$kruskal.options[[1]]
opt.label<- opts$kruskal.options[[2]]
opt.y <- opts$kruskal.options[[3]]
opt.x <- opts$kruskal.options[[4]]
opts$kruskal.options <- NULL
}
pl <- do.call(ggboxplot,opts) # create plot by calling ggboxplot with all user options
if (kruskal){ pl <- pl + stat_kruskal_test(group.by=opt.group,label=opt.label, label.y.npc=opt.y,label.x.npc=opt.x) }
if(!whisk)
{ pl_list <- ggplot_build(pl) # get listed version of ggboxplot object to modify
pl_list$data[[1]]$ymin <- NA # remove the ymin/max that specify the whiskers
pl_list$data[[1]]$ymax <- NA
pl <- ggplot_gtable(pl_list) # convert back to ggplot object
}
# return
pl
}
Here's the application:
set.seed(123)
x <-rnorm(100)
labels <- round(runif(100,1,2))
df <- data.frame(labels=labels, value=x)
# Define the options for the stat_kruskal_test label
KO <- list("group"="labels","label"="as_detailed_italic", "label.y.npc"=0.5,"label.x.npc"=0.5,ylim=c(-1.2, 1.2))
# call the function
output.plot <- ggboxplot_whisker_opt(df, "labels","value", col="labels", legend="none", whisker=FALSE,add=c("mean"), orientation="horizontal" kruskal=TRUE,kruskal.options=KO)
# Plot the result
plot(output.plot)
the issue with modifying was that the returned object was not a ggplot
object anymore (wrong comment on my side) but a plot object. I have thought about it and instead of modifying the ggbuilt object, it's also possible to directly pass the coef=0
through to the geom_boxplot
layer inside the object returned by ggboxplot
:
ggboxplot_whisker_opt <- function(...)
{
opts <- list(...)
# check if user specified a whiskers argument and set options accordingly
if("whisker" %in% names(opts))
{
whisk <- opts$whisker
opts$whisker <- NULL
} else {
whisk <- TRUE
}
pl <- do.call(ggpubr::ggboxplot, opts) # create plot by calling ggboxplot with all user options
if(!whisk)
{
pl$layers[[1]]$stat_params$coef <- 0 # modify coef param of geom_boxplot layer
}
# plot the ggplot and return so other ggplot parts can be added via `+`
pl
}
This function now returns an object compatible with ggpar
or adding other ggplot modifiers via +
library(ggplot2)
library(ggpubr)
set.seed(123)
x <- rnorm(100)
labels <- round(runif(100,1,2))
df <- data.frame(labels=labels,
value=x)
testplot <- ggboxplot_whisker_opt(df,"labels","value",whisker=FALSE)
ggpar(testplot,xlim=c(0.5,1.5),
ylim=c(-0.5,0.5))
testplot +
geom_line(data=data.frame(x=c(1,2),y=c(0,0)),aes(x=x,y=y),color="red",lwd=2)