From d1f00743d50acfc123ed837fba50e4a6b4720556 Mon Sep 17 00:00:00 2001 From: chschan Date: Wed, 28 May 2025 12:49:07 +1000 Subject: [PATCH 1/3] Remove dependency on ggplot2 --- DESCRIPTION | 6 +- NAMESPACE | 15 +-- R/splinewithsimultaneousconfint.R | 108 +++++++++++++++++---- man/SplineWithSimultaneousConfIntervals.Rd | 78 ++++++++++++++- 4 files changed, 171 insertions(+), 36 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index be99668..58af8d5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: flipPlots Type: Package Title: Creates Plots -Version: 1.3.7 +Version: 1.3.8 Author: Displayr Maintainer: Displayr Description: Wrappers for various plot types. @@ -9,13 +9,12 @@ License: GPL-3 LazyData: FALSE Imports: flipTransformations, + flipStandardCharts, flipU (>= 1.6.2), networkD3, mgcv, - ggplot2 (<= 3.4.4), plotly, scales, - rlang, verbs Suggests: flipExampleData, @@ -23,6 +22,7 @@ Suggests: testthat, Remotes: Displayr/flipTransformations, + Displayr/flipStandardCharts, Displayr/flipU, Displayr/networkD3, Displayr/plotly, diff --git a/NAMESPACE b/NAMESPACE index 0f2e58d..c6233be 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,29 +2,24 @@ export(SankeyDiagram) export(SplineWithSimultaneousConfIntervals) +importFrom(flipStandardCharts,Line) importFrom(flipTransformations,AdjustDataToReflectWeights) importFrom(flipTransformations,AsNumeric) importFrom(flipTransformations,DichotomizeFactor) importFrom(flipTransformations,Factor) importFrom(flipU,MakeUniqueNames) importFrom(flipU,StopForUserError) -importFrom(ggplot2,aes) -importFrom(ggplot2,geom_path) -importFrom(ggplot2,geom_ribbon) -importFrom(ggplot2,ggplot) -importFrom(ggplot2,labs) -importFrom(ggplot2,scale_y_continuous) -importFrom(ggplot2,theme_bw) -importFrom(ggplot2,theme_set) importFrom(grDevices,col2rgb) importFrom(grDevices,rgb) importFrom(mgcv,gam) importFrom(mgcv,mroot) importFrom(networkD3,JS) importFrom(networkD3,sankeyNetwork) +importFrom(plotly,add_lines) +importFrom(plotly,add_ribbons) importFrom(plotly,config) -importFrom(plotly,ggplotly) -importFrom(rlang,.data) +importFrom(plotly,layout) +importFrom(plotly,plot_ly) importFrom(scales,percent) importFrom(stats,binomial) importFrom(stats,coef) diff --git a/R/splinewithsimultaneousconfint.R b/R/splinewithsimultaneousconfint.R index 40dc87f..2b4d92c 100644 --- a/R/splinewithsimultaneousconfint.R +++ b/R/splinewithsimultaneousconfint.R @@ -1,5 +1,6 @@ #' Plots spline with confidence intervals #' +#' @inheritParams flipStandardCharts::Line #' @param outcome Outcome variable shown in the y-axis. This should be convertible using \code{AsNumeric}. #' @param predictor Predictor variable shown in the x-axis. This should be a numeric or date variable. #' @param type Regression link function used. Currently can be "Binary Logit" or "Linear". @@ -9,17 +10,25 @@ #' @param weights Optional numeric vector used as sampling weights. #' @param seed Random seed for reproducibility #' @param confidence Width of confidence interval shown around the spline. +#' @param ci.color Color of the ribbon showing the confidence interval. #' @param number.draws Number of possible trend lines to super-impose. -#' @param trim.padding Logical; whether to remove padding around plotly chart. +#' @param draw.color Color of the possible trend lines. +#' @param draw.weight Line weight of the possible trend line. +#' @param mean.color Line color of the mean (or predicted) line. +#' @param mean.weight Line weight of the mean line. +#' @param font.units One of "px" of "pt". By default all font sizes are specified in terms of +#' pixels ("px"). But changing this to "pt" will mean that the font sizes will be in terms +#' points ("pt"), which will be consistent with font sizes in text boxes. +#' @param trim.padding (Deprecated)Logical; whether to remove padding around plotly chart. #' Default is set to false so that output is the same as old charts. +#' @param ... Other parameters to pass to flipStandardCharts::Line. +#' @importFrom flipStandardCharts Line #' @importFrom flipTransformations AsNumeric AdjustDataToReflectWeights DichotomizeFactor #' @importFrom flipU StopForUserError #' @importFrom mgcv gam mroot -#' @importFrom ggplot2 ggplot geom_ribbon geom_path aes theme_set theme_bw labs scale_y_continuous -#' @importFrom plotly ggplotly config +#' @importFrom plotly plot_ly add_ribbons add_lines layout config #' @importFrom utils stack #' @importFrom scales percent -#' @importFrom rlang .data #' @importFrom stats binomial coef complete.cases family predict quantile rnorm vcov gaussian #' @importFrom verbs Sum #' @export @@ -31,7 +40,29 @@ SplineWithSimultaneousConfIntervals <- function(outcome, seed = 42, number.draws = 30, confidence = 0.95, - trim.padding = FALSE) + mean.color = "#000000", + mean.weight = 2, + draw.color = "#33333366", + draw.weight = 1, + ci.color = "#FF000033", + y.tick.format = NULL, + y.hovertext.format = ".1f", + title = NULL, + subtitle = NULL, + x.title = NULL, + y.title = NULL, + global.font.family = "Arial", + global.font.color = rgb(44, 44, 44, maxColorValue = 255), + title.font.size = 16, + subtitle.font.size = 12, + hovertext.font.size = 11, + y.title.font.size = 12, + x.title.font.size = 12, + y.tick.font.size = 10, + x.tick.font.size = 10, + font.units = "pt", + trim.padding = FALSE, + ...) { if (length(unique(outcome)) == 1) StopForUserError("Could not construct model as outcome variable contains only one value.") @@ -115,14 +146,49 @@ SplineWithSimultaneousConfIntervals <- function(outcome, sims <- rmvn(N, mu = coef(m), sig = Vb) fits <- Cg %*% t(sims) + if (is.null(title)) + title <- paste0("Simultaneous ", confidence * 100, "% confidence intervals for fitted GAM") + if (is.null(subtitle)) + subtitle = sprintf("Each line is one of %i draws from the Bayesian posterior distribution of the model", number.draws) + if (is.null(x.title)) + x.title <- xlab + if (is.null(y.title)) + y.title <- ylab + if (is.null(y.tick.format) && logit) + y.tick.format <- "%" + + # For the standard charts, the font size conversion happens inside flipChart::CChart + if (tolower(font.units) %in% c("pt", "point", "points")) + { + fsc <- 1.3333 + title.font.size = round(fsc * title.font.size, 0) + subtitle.font.size = round(fsc * subtitle.font.size, 0) + hovertext.font.size = round(fsc * hovertext.font.size, 0) + y.title.font.size = round(fsc * y.title.font.size, 0) + x.title.font.size = round(fsc * x.title.font.size, 0) + y.tick.font.size = round(fsc * y.tick.font.size, 0) + x.tick.font.size = round(fsc * x.tick.font.size, 0) + } + # Create plot - theme_set(theme_bw()) - p <- ggplot(pred, aes(x = .data$predictor, y = .data$fit)) + - geom_ribbon(aes(ymin = .data$lwrS, ymax = .data$uprS), alpha = 0.2, fill = "red") + - geom_path(lwd = 2) + - labs(y = ylab, x = xlab, - title = paste0("Simultaneous ", confidence * 100, "% confidence intervals for fitted GAM"), - subtitle = sprintf("Each line is one of %i draws from the Bayesian posterior distribution of the model", number.draws)) + plot.data <- pred$fit + names(plot.data) <- pred$predictor + pp <- Line(plot.data, colors = mean.color, line.thickness = mean.weight, + title = title, subtitle = subtitle, x.title = x.title, y.title = y.title, + y.tick.format = y.tick.format, y.hovertext.format = y.hovertext.format, + global.font.family = global.font.family, global.font.color = global.font.color, + title.font.size = title.font.size, subtitle.font.size = subtitle.font.size, + y.title.font.size = y.title.font.size, x.title.font.size = x.title.font.size, + y.tick.font.size = y.tick.font.size, x.tick.font.size = x.tick.font.size, + hovertext.font.size = hovertext.font.size, legend.show = FALSE, ...) + + pp$htmlwidget <- add_ribbons(pp$htmlwidget, x = pred$predictor, + ymin = pred$lwrS, ymax = pred$uprS, + fillcolor = ci.color, line = list(color = "transparent"), + text = sprintf(paste0("[%", y.hovertext.format, ", %", y.hovertext.format, "]"), pred$lwrS, pred$uprS), + hovertemplate = "%{x}: %{text}", + hoverlabel = list(font = list(color = flipStandardCharts:::autoFontColor(ci.color))), + name = "Confidence Interval") if (number.draws > 0) { @@ -131,14 +197,14 @@ SplineWithSimultaneousConfIntervals <- function(outcome, else stack(as.data.frame(fits[, rnd])) stackFits <- transform(stackFits, predictor.numeric = rep(newd$predictor.numeric, length(rnd))) stackFits$predictor = newd$predictor - p = p + geom_path(data = stackFits, - mapping = aes(y = .data$values, x = .data$predictor, group = .data$ind), - alpha = 0.4, colour = "grey20") + for (i in unique(stackFits$ind)) + { + ind <- which(stackFits$ind == i) + pp$htmlwidget <- add_lines(pp$htmlwidget, x = stackFits$predictor[ind], y = stackFits$values[ind], + line = list(color = draw.color, width = draw.weight), + hoverlabel = list(font = list(color = flipStandardCharts:::autoFontColor(draw.color))), + name = paste("Draw", i)) + } } - if (logit) - p <- p + scale_y_continuous(labels = percent) - p <- ggplotly(p) - p <- config(p, displayModeBar = FALSE) - p$sizingPolicy$browser$padding <- if (trim.padding) 0 else 40 - p + pp } diff --git a/man/SplineWithSimultaneousConfIntervals.Rd b/man/SplineWithSimultaneousConfIntervals.Rd index f6de87d..af38714 100644 --- a/man/SplineWithSimultaneousConfIntervals.Rd +++ b/man/SplineWithSimultaneousConfIntervals.Rd @@ -13,7 +13,29 @@ SplineWithSimultaneousConfIntervals( seed = 42, number.draws = 30, confidence = 0.95, - trim.padding = FALSE + mean.color = "#000000", + mean.weight = 2, + draw.color = "#33333366", + draw.weight = 1, + ci.color = "#FF000033", + y.tick.format = NULL, + y.hovertext.format = ".1f", + title = NULL, + subtitle = NULL, + x.title = NULL, + y.title = NULL, + global.font.family = "Arial", + global.font.color = rgb(44, 44, 44, maxColorValue = 255), + title.font.size = 16, + subtitle.font.size = 12, + hovertext.font.size = 11, + y.title.font.size = 12, + x.title.font.size = 12, + y.tick.font.size = 10, + x.tick.font.size = 10, + font.units = "pt", + trim.padding = FALSE, + ... ) } \arguments{ @@ -35,8 +57,60 @@ in the analysis.} \item{confidence}{Width of confidence interval shown around the spline.} -\item{trim.padding}{Logical; whether to remove padding around plotly chart. +\item{mean.color}{Line color of the mean (or predicted) line.} + +\item{mean.weight}{Line weight of the mean line.} + +\item{draw.color}{Color of the possible trend lines.} + +\item{draw.weight}{Line weight of the possible trend line.} + +\item{ci.color}{Color of the ribbon showing the confidence interval.} + +\item{y.tick.format}{A string representing a d3 formatting code. +See https://github.com/d3/d3/blob/master/API.md#number-formats-d3-format} + +\item{y.hovertext.format}{A string representing a d3 formatting code +See https://github.com/d3/d3/blob/master/API.md#number-formats-d3-format} + +\item{title}{Character; chart title.} + +\item{subtitle}{Character} + +\item{x.title}{Character, x-axis title; defaults to chart input values; +to turn off set to "FALSE".} + +\item{y.title}{Character, y-axis title; defaults to chart input values; +to turn off set to "FALSE".} + +\item{global.font.family}{Character; font family for all occurrences of any +font attribute for the chart unless specified individually.} + +\item{global.font.color}{Global font color as a named color in character format +(e.g. "black") or an a hex code.} + +\item{title.font.size}{Integer; Title font size; default = 10.} + +\item{subtitle.font.size}{Integer; subtitle font size} + +\item{hovertext.font.size}{Font size of hover text.} + +\item{y.title.font.size}{Integer; y-axis title font size} + +\item{x.title.font.size}{Integer; x-axis title font size} + +\item{y.tick.font.size}{Integer; y-axis tick label font size} + +\item{x.tick.font.size}{Integer; x-axis tick label font size} + +\item{font.units}{One of "px" of "pt". By default all font sizes are specified in terms of +pixels ("px"). But changing this to "pt" will mean that the font sizes will be in terms +points ("pt"), which will be consistent with font sizes in text boxes.} + +\item{trim.padding}{(Deprecated)Logical; whether to remove padding around plotly chart. Default is set to false so that output is the same as old charts.} + +\item{...}{Other parameters to pass to flipStandardCharts::Line.} } \description{ Plots spline with confidence intervals From e0f96c85100231b81a5a0ee525368f5238f649a3 Mon Sep 17 00:00:00 2001 From: chschan Date: Tue, 10 Jun 2025 12:25:56 +1000 Subject: [PATCH 2/3] Change font defaults to match Plugins --- R/splinewithsimultaneousconfint.R | 16 ++++++++-------- man/SplineWithSimultaneousConfIntervals.Rd | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/R/splinewithsimultaneousconfint.R b/R/splinewithsimultaneousconfint.R index 2b4d92c..b5dfaa3 100644 --- a/R/splinewithsimultaneousconfint.R +++ b/R/splinewithsimultaneousconfint.R @@ -51,15 +51,15 @@ SplineWithSimultaneousConfIntervals <- function(outcome, subtitle = NULL, x.title = NULL, y.title = NULL, - global.font.family = "Arial", + global.font.family = "Open Sans", global.font.color = rgb(44, 44, 44, maxColorValue = 255), - title.font.size = 16, - subtitle.font.size = 12, - hovertext.font.size = 11, - y.title.font.size = 12, - x.title.font.size = 12, - y.tick.font.size = 10, - x.tick.font.size = 10, + title.font.size = 12, + subtitle.font.size = 8, + hovertext.font.size = 9, + y.title.font.size = 10, + x.title.font.size = 10, + y.tick.font.size = 9, + x.tick.font.size = 9, font.units = "pt", trim.padding = FALSE, ...) diff --git a/man/SplineWithSimultaneousConfIntervals.Rd b/man/SplineWithSimultaneousConfIntervals.Rd index af38714..592ab85 100644 --- a/man/SplineWithSimultaneousConfIntervals.Rd +++ b/man/SplineWithSimultaneousConfIntervals.Rd @@ -24,15 +24,15 @@ SplineWithSimultaneousConfIntervals( subtitle = NULL, x.title = NULL, y.title = NULL, - global.font.family = "Arial", + global.font.family = "Open Sans", global.font.color = rgb(44, 44, 44, maxColorValue = 255), - title.font.size = 16, - subtitle.font.size = 12, - hovertext.font.size = 11, - y.title.font.size = 12, - x.title.font.size = 12, - y.tick.font.size = 10, - x.tick.font.size = 10, + title.font.size = 12, + subtitle.font.size = 8, + hovertext.font.size = 9, + y.title.font.size = 10, + x.title.font.size = 10, + y.tick.font.size = 9, + x.tick.font.size = 9, font.units = "pt", trim.padding = FALSE, ... From 534285dd5473e6610e78fa5c02db13972f2c9fd1 Mon Sep 17 00:00:00 2001 From: chschan Date: Tue, 10 Jun 2025 13:39:04 +1000 Subject: [PATCH 3/3] Remove subtitle; show x-axis grid lines --- R/splinewithsimultaneousconfint.R | 10 +++------- man/SplineWithSimultaneousConfIntervals.Rd | 9 +++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/R/splinewithsimultaneousconfint.R b/R/splinewithsimultaneousconfint.R index b5dfaa3..c51e60e 100644 --- a/R/splinewithsimultaneousconfint.R +++ b/R/splinewithsimultaneousconfint.R @@ -46,15 +46,14 @@ SplineWithSimultaneousConfIntervals <- function(outcome, draw.weight = 1, ci.color = "#FF000033", y.tick.format = NULL, + x.grid.width = 1, y.hovertext.format = ".1f", title = NULL, - subtitle = NULL, x.title = NULL, y.title = NULL, global.font.family = "Open Sans", global.font.color = rgb(44, 44, 44, maxColorValue = 255), title.font.size = 12, - subtitle.font.size = 8, hovertext.font.size = 9, y.title.font.size = 10, x.title.font.size = 10, @@ -148,8 +147,6 @@ SplineWithSimultaneousConfIntervals <- function(outcome, if (is.null(title)) title <- paste0("Simultaneous ", confidence * 100, "% confidence intervals for fitted GAM") - if (is.null(subtitle)) - subtitle = sprintf("Each line is one of %i draws from the Bayesian posterior distribution of the model", number.draws) if (is.null(x.title)) x.title <- xlab if (is.null(y.title)) @@ -162,7 +159,6 @@ SplineWithSimultaneousConfIntervals <- function(outcome, { fsc <- 1.3333 title.font.size = round(fsc * title.font.size, 0) - subtitle.font.size = round(fsc * subtitle.font.size, 0) hovertext.font.size = round(fsc * hovertext.font.size, 0) y.title.font.size = round(fsc * y.title.font.size, 0) x.title.font.size = round(fsc * x.title.font.size, 0) @@ -174,10 +170,10 @@ SplineWithSimultaneousConfIntervals <- function(outcome, plot.data <- pred$fit names(plot.data) <- pred$predictor pp <- Line(plot.data, colors = mean.color, line.thickness = mean.weight, - title = title, subtitle = subtitle, x.title = x.title, y.title = y.title, + title = title, x.title = x.title, y.title = y.title, y.tick.format = y.tick.format, y.hovertext.format = y.hovertext.format, global.font.family = global.font.family, global.font.color = global.font.color, - title.font.size = title.font.size, subtitle.font.size = subtitle.font.size, + title.font.size = title.font.size, x.grid.width = x.grid.width, y.title.font.size = y.title.font.size, x.title.font.size = x.title.font.size, y.tick.font.size = y.tick.font.size, x.tick.font.size = x.tick.font.size, hovertext.font.size = hovertext.font.size, legend.show = FALSE, ...) diff --git a/man/SplineWithSimultaneousConfIntervals.Rd b/man/SplineWithSimultaneousConfIntervals.Rd index 592ab85..26fad3d 100644 --- a/man/SplineWithSimultaneousConfIntervals.Rd +++ b/man/SplineWithSimultaneousConfIntervals.Rd @@ -19,15 +19,14 @@ SplineWithSimultaneousConfIntervals( draw.weight = 1, ci.color = "#FF000033", y.tick.format = NULL, + x.grid.width = 1, y.hovertext.format = ".1f", title = NULL, - subtitle = NULL, x.title = NULL, y.title = NULL, global.font.family = "Open Sans", global.font.color = rgb(44, 44, 44, maxColorValue = 255), title.font.size = 12, - subtitle.font.size = 8, hovertext.font.size = 9, y.title.font.size = 10, x.title.font.size = 10, @@ -70,13 +69,13 @@ in the analysis.} \item{y.tick.format}{A string representing a d3 formatting code. See https://github.com/d3/d3/blob/master/API.md#number-formats-d3-format} +\item{x.grid.width}{Width of y-grid lines in pixels; 0 = no line} + \item{y.hovertext.format}{A string representing a d3 formatting code See https://github.com/d3/d3/blob/master/API.md#number-formats-d3-format} \item{title}{Character; chart title.} -\item{subtitle}{Character} - \item{x.title}{Character, x-axis title; defaults to chart input values; to turn off set to "FALSE".} @@ -91,8 +90,6 @@ font attribute for the chart unless specified individually.} \item{title.font.size}{Integer; Title font size; default = 10.} -\item{subtitle.font.size}{Integer; subtitle font size} - \item{hovertext.font.size}{Font size of hover text.} \item{y.title.font.size}{Integer; y-axis title font size}