diff --git a/DESCRIPTION b/DESCRIPTION
index 27badc44..ce246736 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -79,6 +79,7 @@ Collate:
'plot-histogram.R'
'plot-obs-vs-pred.R'
'plot-pkratio.R'
+ 'plot-qq.R'
'plot-res-vs-pred.R'
'plot-timeprofile.R'
'plot-tornado.R'
@@ -88,6 +89,7 @@ Collate:
'plotconfiguration-label.R'
'plotconfiguration-legend.R'
'plotconfiguration.R'
+ 'qq-datamapping.R'
'themes.R'
'timeprofile-datamapping.R'
'timeprofile-helper.R'
diff --git a/NAMESPACE b/NAMESPACE
index acf90922..527449eb 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -66,6 +66,8 @@ export(PKRatioPlotConfiguration)
export(PlotAnnotationTextSize)
export(PlotConfiguration)
export(PlotGridConfiguration)
+export(QQDataMapping)
+export(QQPlotConfiguration)
export(RangeDataMapping)
export(ResVsPredDataMapping)
export(ResVsPredPlotConfiguration)
@@ -111,6 +113,7 @@ export(getLinesFromFoldDistance)
export(getLnTickLabels)
export(getLogTickLabels)
export(getPKRatioMeasure)
+export(getPercentileTickLabels)
export(getPiTickLabels)
export(getSameLimits)
export(getSqrtTickLabels)
@@ -123,6 +126,7 @@ export(plotGrid)
export(plotHistogram)
export(plotObsVsPred)
export(plotPKRatio)
+export(plotQQ)
export(plotResVsPred)
export(plotResVsTime)
export(plotTimeProfile)
diff --git a/R/plot-qq.R b/R/plot-qq.R
new file mode 100644
index 00000000..621559b2
--- /dev/null
+++ b/R/plot-qq.R
@@ -0,0 +1,108 @@
+#' @title plotQQ
+#' @description
+#' Producing Histograms
+#'
+#' @inheritParams addScatter
+#' @param dataMapping
+#' A `QQDataMapping` object mapping `y` and aesthetic groups to their variable names of `data`.
+#' @param plotConfiguration
+#' An optional `QQPlotConfiguration` object defining labels, grid, background and watermark.
+#' @return A `ggplot` object
+#'
+#' @export
+#' @family molecule plots
+#' @examples
+#' # Produce QQ plot of normally distributed data
+#' plotQQ(y = rnorm(100))
+#'
+#' # Produce QQ plot of normally distributed data split by group
+#' qqData <- data.frame(
+#' residuals = c(rnorm(100), rnorm(100)),
+#' groups = c(rep("Group A", 100), rep("Group B", 100))
+#' )
+#' plotQQ(
+#' data = qqData,
+#' dataMapping = QQDataMapping$new(y = "residuals", group = "groups")
+#' )
+#'
+plotQQ <- function(data = NULL,
+ metaData = NULL,
+ y = NULL,
+ dataMapping = NULL,
+ plotConfiguration = NULL,
+ plotObject = NULL) {
+ #----- Validation and formatting of input arguments -----
+ if (is.null(data)) {
+ validateIsNumeric(y)
+ data <- data.frame(y = y)
+ dataMapping <- dataMapping %||% QQDataMapping$new(
+ y = "y",
+ data = data
+ )
+ }
+ validateIsNotEmpty(data)
+ validateIsOfType(data, "data.frame")
+ dataMapping <- .setDataMapping(dataMapping, QQDataMapping, data)
+
+ plotConfiguration <- .setPlotConfiguration(
+ plotConfiguration, QQPlotConfiguration,
+ data, metaData, dataMapping
+ )
+ plotObject <- .setPlotObject(plotObject, plotConfiguration)
+
+ mapData <- dataMapping$checkMapData(data)
+ mapLabels <- .getAesStringMapping(dataMapping)
+
+ #----- Build layers of molecule plot -----
+ # 1- Line layer
+ aestheticValues <- .getAestheticValuesFromConfiguration(
+ n = 1,
+ plotConfigurationProperty = plotObject$plotConfiguration$lines,
+ propertyNames = c("color", "size", "alpha", "linetype")
+ )
+
+ plotObject <- plotObject +
+ ggplot2::geom_qq_line(
+ data = mapData,
+ mapping = ggplot2::aes_string(
+ sample = mapLabels$y
+ ),
+ size = aestheticValues$size,
+ color = aestheticValues$color,
+ linetype = aestheticValues$linetype,
+ alpha = aestheticValues$alpha,
+ na.rm = TRUE
+ )
+
+ # 2- Scatter point layer
+ aestheticValues <- .getAestheticValuesFromConfiguration(
+ n = 1,
+ plotConfigurationProperty = plotObject$plotConfiguration$points,
+ propertyNames = c("size", "alpha")
+ )
+
+ plotObject <- plotObject +
+ ggplot2::geom_point(
+ data = mapData,
+ mapping = ggplot2::aes_string(
+ x = DefaultDataMappingValues$qqPlot,
+ y = mapLabels$y,
+ color = mapLabels$color,
+ shape = mapLabels$shape
+ ),
+ size = aestheticValues$size,
+ alpha = aestheticValues$alpha,
+ na.rm = TRUE
+ )
+
+ #----- Update properties using ggplot2::scale functions -----
+ plotObject <- .updateAesProperties(
+ plotObject,
+ plotConfigurationProperty = "points",
+ propertyNames = c("color", "shape"),
+ data = mapData,
+ mapLabels = mapLabels
+ )
+ plotObject <- .updateAxes(plotObject)
+ return(plotObject)
+}
diff --git a/R/plotconfiguration-axis.R b/R/plotconfiguration-axis.R
index 0b0a7ade..ff021d5e 100644
--- a/R/plotconfiguration-axis.R
+++ b/R/plotconfiguration-axis.R
@@ -180,6 +180,7 @@ AxisConfiguration <- R6::R6Class(
"log" = getLogTickLabels,
"ln" = getLnTickLabels,
"sqrt" = getSqrtTickLabels,
+ "percentiles" = getPercentileTickLabels,
private$.ticklabels
)
}
diff --git a/R/plotconfiguration.R b/R/plotconfiguration.R
index 89cc36a1..d3a3befc 100644
--- a/R/plotconfiguration.R
+++ b/R/plotconfiguration.R
@@ -367,3 +367,22 @@ HistogramPlotConfiguration <- R6::R6Class(
}
)
)
+
+#' @title QQPlotConfiguration
+#' @description R6 class defining the configuration of a `ggplot` object for Quantile-Quantile plots
+#' @export
+#' @family PlotConfiguration classes
+QQPlotConfiguration <- R6::R6Class(
+ "QQPlotConfiguration",
+ inherit = PlotConfiguration,
+ public = list(
+ #' @description Create a new `QQPlotConfiguration` object
+ #' @param xlabel QQ-plot default display is "Standard Normal Quantiles"
+ #' @param ... parameters inherited from `PlotConfiguration`
+ #' @return A new `QQPlotConfiguration` object
+ initialize = function(xlabel = "Standard Normal Quantiles",
+ ...) {
+ super$initialize(xlabel = xlabel, ...)
+ }
+ )
+)
diff --git a/R/qq-datamapping.R b/R/qq-datamapping.R
new file mode 100644
index 00000000..f453ee08
--- /dev/null
+++ b/R/qq-datamapping.R
@@ -0,0 +1,26 @@
+#' @title QQDataMapping
+#' @description R6 class for mapping `x`, `y` and `GroupMapping` variables to `data`
+#' @export
+#' @family DataMapping classes
+QQDataMapping <- R6::R6Class(
+ "QQDataMapping",
+ inherit = XYGDataMapping,
+ public = list(
+ #' @description Check that `data` variables include map variables
+ #' @param data data.frame to check
+ #' @param metaData list containing information on `data`
+ #' @return A data.frame with map and `defaultAes` variables.
+ #' Dummy variable `defaultAes` is necessary to allow further modification of plots.
+ checkMapData = function(data, metaData = NULL) {
+ validateIsOfType(data, "data.frame")
+ mapData <- super$checkMapData(data, metaData)
+ if (isEmpty(self$x)) {
+ # Get theoritical quantiles for normal distribution
+ xQuantiles <- stats::qqnorm(data[, self$y], plot.it = FALSE)$x
+ mapData[, DefaultDataMappingValues$qqPlot] <- xQuantiles
+ }
+ self$data <- mapData
+ return(mapData)
+ }
+ )
+)
diff --git a/R/utilities-axis.R b/R/utilities-axis.R
index 7f24acd9..de1aa023 100644
--- a/R/utilities-axis.R
+++ b/R/utilities-axis.R
@@ -219,6 +219,23 @@ getPiTickLabels <- function(ticks) {
return(piLabels)
}
+#' @title getPercentileTickLabels
+#' @description Get ticklabels expressions for percentiles of normal distribution scale plots
+#' @param ticks numeric values of the ticks
+#' @return Expressions to use in `ticklabels` input parameter of `setXAxis` and `setYAxis` functions
+#' @examples
+#' ticks <- rnorm(5)
+#' getPercentileTickLabels(ticks)
+#'
+#' # Get percentile of normal distribution
+#' ticks <- qnorm(seq(1, 9) / 10)
+#' getPercentileTickLabels(ticks)
+#'
+#' @export
+getPercentileTickLabels <- function(ticks) {
+ return(paste0(round(100 * stats::pnorm(ticks), 3), "%"))
+}
+
#' @title .removeInfiniteValues
#' @description Censor/remove any values outside of range
#' Caution, removing infinite values can cause issues with ribbons
diff --git a/R/utilities-enums.R b/R/utilities-enums.R
index 2d14e40b..df338570 100644
--- a/R/utilities-enums.R
+++ b/R/utilities-enums.R
@@ -329,4 +329,4 @@ ExportFormats <- enum(c("png", "pdf", "eps", "ps", "tex", "jpeg", "tiff", "bmp",
#' @description
#' List of all available tick label transformation names
#' @family enum helpers
-TickLabelTransforms <- enum(c("none", "default", "identity", "log", "ln", "sqrt", "greek", "pi"))
+TickLabelTransforms <- enum(c("none", "default", "identity", "log", "ln", "sqrt", "greek", "pi", "percentiles"))
diff --git a/R/utilities-mapping.R b/R/utilities-mapping.R
index cb1e9982..6703b789 100644
--- a/R/utilities-mapping.R
+++ b/R/utilities-mapping.R
@@ -274,7 +274,8 @@ DefaultDataMappingValues <- list(
),
resVsPred = 0,
tornado = 0,
- histogram = 0
+ histogram = 0,
+ qqPlot = "StandardNormalQuantiles"
)
#' @title getLinesFromFoldDistance
diff --git a/man/BoxWhiskerDataMapping.Rd b/man/BoxWhiskerDataMapping.Rd
index 65ac3429..46183679 100644
--- a/man/BoxWhiskerDataMapping.Rd
+++ b/man/BoxWhiskerDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/BoxWhiskerPlotConfiguration.Rd b/man/BoxWhiskerPlotConfiguration.Rd
index cac5e548..bc04f901 100644
--- a/man/BoxWhiskerPlotConfiguration.Rd
+++ b/man/BoxWhiskerPlotConfiguration.Rd
@@ -13,6 +13,7 @@ Other PlotConfiguration classes:
\code{\link{ObsVsPredPlotConfiguration}},
\code{\link{PKRatioPlotConfiguration}},
\code{\link{PlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/DDIRatioDataMapping.Rd b/man/DDIRatioDataMapping.Rd
index 148e38b9..d0c9a89c 100644
--- a/man/DDIRatioDataMapping.Rd
+++ b/man/DDIRatioDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/DDIRatioPlotConfiguration.Rd b/man/DDIRatioPlotConfiguration.Rd
index 3630ca14..474869b0 100644
--- a/man/DDIRatioPlotConfiguration.Rd
+++ b/man/DDIRatioPlotConfiguration.Rd
@@ -13,6 +13,7 @@ Other PlotConfiguration classes:
\code{\link{ObsVsPredPlotConfiguration}},
\code{\link{PKRatioPlotConfiguration}},
\code{\link{PlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/DefaultDataMappingValues.Rd b/man/DefaultDataMappingValues.Rd
index d08ce537..75eec9c3 100644
--- a/man/DefaultDataMappingValues.Rd
+++ b/man/DefaultDataMappingValues.Rd
@@ -5,7 +5,7 @@
\alias{DefaultDataMappingValues}
\title{DefaultDataMappingValues}
\format{
-An object of class \code{list} of length 6.
+An object of class \code{list} of length 7.
}
\usage{
DefaultDataMappingValues
diff --git a/man/GroupMapping.Rd b/man/GroupMapping.Rd
index 2c051c46..62c6f952 100644
--- a/man/GroupMapping.Rd
+++ b/man/GroupMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/Grouping.Rd b/man/Grouping.Rd
index 01b7625b..ef289eff 100644
--- a/man/Grouping.Rd
+++ b/man/Grouping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/HistogramDataMapping.Rd b/man/HistogramDataMapping.Rd
index 00d2eec3..e592b6ea 100644
--- a/man/HistogramDataMapping.Rd
+++ b/man/HistogramDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/HistogramPlotConfiguration.Rd b/man/HistogramPlotConfiguration.Rd
index 17bb9982..fabdba40 100644
--- a/man/HistogramPlotConfiguration.Rd
+++ b/man/HistogramPlotConfiguration.Rd
@@ -13,6 +13,7 @@ Other PlotConfiguration classes:
\code{\link{ObsVsPredPlotConfiguration}},
\code{\link{PKRatioPlotConfiguration}},
\code{\link{PlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/ObsVsPredDataMapping.Rd b/man/ObsVsPredDataMapping.Rd
index 8e73041c..4aaefaae 100644
--- a/man/ObsVsPredDataMapping.Rd
+++ b/man/ObsVsPredDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{HistogramDataMapping}},
\code{\link{ObservedDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/ObsVsPredPlotConfiguration.Rd b/man/ObsVsPredPlotConfiguration.Rd
index 51d5764b..16c72407 100644
--- a/man/ObsVsPredPlotConfiguration.Rd
+++ b/man/ObsVsPredPlotConfiguration.Rd
@@ -13,6 +13,7 @@ Other PlotConfiguration classes:
\code{\link{HistogramPlotConfiguration}},
\code{\link{PKRatioPlotConfiguration}},
\code{\link{PlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/ObservedDataMapping.Rd b/man/ObservedDataMapping.Rd
index 3ca6c338..0ed15ba3 100644
--- a/man/ObservedDataMapping.Rd
+++ b/man/ObservedDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{HistogramDataMapping}},
\code{\link{ObsVsPredDataMapping}},
\code{\link{PKRatioDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/PKRatioDataMapping.Rd b/man/PKRatioDataMapping.Rd
index a667392f..4dd6a5e8 100644
--- a/man/PKRatioDataMapping.Rd
+++ b/man/PKRatioDataMapping.Rd
@@ -15,6 +15,7 @@ Other DataMapping classes:
\code{\link{HistogramDataMapping}},
\code{\link{ObsVsPredDataMapping}},
\code{\link{ObservedDataMapping}},
+\code{\link{QQDataMapping}},
\code{\link{RangeDataMapping}},
\code{\link{ResVsPredDataMapping}},
\code{\link{ResVsTimeDataMapping}},
diff --git a/man/PKRatioPlotConfiguration.Rd b/man/PKRatioPlotConfiguration.Rd
index b96233ce..75c2f175 100644
--- a/man/PKRatioPlotConfiguration.Rd
+++ b/man/PKRatioPlotConfiguration.Rd
@@ -13,6 +13,7 @@ Other PlotConfiguration classes:
\code{\link{HistogramPlotConfiguration}},
\code{\link{ObsVsPredPlotConfiguration}},
\code{\link{PlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/PlotConfiguration.Rd b/man/PlotConfiguration.Rd
index 04b6ef36..2fd3eb0c 100644
--- a/man/PlotConfiguration.Rd
+++ b/man/PlotConfiguration.Rd
@@ -17,6 +17,7 @@ Other PlotConfiguration classes:
\code{\link{HistogramPlotConfiguration}},
\code{\link{ObsVsPredPlotConfiguration}},
\code{\link{PKRatioPlotConfiguration}},
+\code{\link{QQPlotConfiguration}},
\code{\link{TimeProfilePlotConfiguration}},
\code{\link{TornadoPlotConfiguration}}
}
diff --git a/man/QQDataMapping.Rd b/man/QQDataMapping.Rd
new file mode 100644
index 00000000..ad2db61d
--- /dev/null
+++ b/man/QQDataMapping.Rd
@@ -0,0 +1,85 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/qq-datamapping.R
+\name{QQDataMapping}
+\alias{QQDataMapping}
+\title{QQDataMapping}
+\description{
+R6 class for mapping \code{x}, \code{y} and \code{GroupMapping} variables to \code{data}
+}
+\seealso{
+Other DataMapping classes:
+\code{\link{BoxWhiskerDataMapping}},
+\code{\link{DDIRatioDataMapping}},
+\code{\link{GroupMapping}},
+\code{\link{Grouping}},
+\code{\link{HistogramDataMapping}},
+\code{\link{ObsVsPredDataMapping}},
+\code{\link{ObservedDataMapping}},
+\code{\link{PKRatioDataMapping}},
+\code{\link{RangeDataMapping}},
+\code{\link{ResVsPredDataMapping}},
+\code{\link{ResVsTimeDataMapping}},
+\code{\link{TimeProfileDataMapping}},
+\code{\link{TornadoDataMapping}},
+\code{\link{XYDataMapping}},
+\code{\link{XYGDataMapping}}
+}
+\concept{DataMapping classes}
+\section{Super classes}{
+\code{tlf::XYDataMapping} -> \code{tlf::XYGDataMapping} -> \code{QQDataMapping}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-QQDataMapping-checkMapData}{\code{QQDataMapping$checkMapData()}}
+\item \href{#method-QQDataMapping-clone}{\code{QQDataMapping$clone()}}
+}
+}
+\if{html}{\out{
+Inherited methods
+
+