# Plot methods for renderOptPathPlot. Nearly the same interface for all plot functions
# Not all functions do have all arguments.
# @param op
# The optimization path
# @param .alpha [\code{numeric}]\cr
# Vector of alpha values for the points in the plots.
# @param .type [\code{factor}]\cr
# Vector of types of the points, factor levels are init, seq, prob and marked.
# @param dob [\code{numeric}]\cr
# Vector of dobs
# @param log[\code{character}]\cr
# Vector of variables to be logarithmized
# @param names [\code{character}]\cr
# Vector of the names of the variables. Used to identify variables for the plot.
# @param short.names [\code{character}]\cr
# Vector of the short names of the variables. This names will be printed in the plot.
# Must be the same length as names
# @param space[\code{character}]
# If the X-Space is plotted, space = "x", if the Y-Space is plotted, space = "y".
# Special case 1D -> 1D also "both" is possible.
# @param iter [\code{integer(1)}]\cr
# Current iteration.
# @param classes [\code{character(2)}]\cr
# Classes of the variables (numeric or factor) in 2D plots.
# @param xlim, ylim [\code{numeric(2)}]\cr
# Limits for the x and y axis respectively.
# @param colours [\code{character(4)}]\cr
# Colours of the points/lines for the three point types init, seq, prob and marked.
# @param size [\code{numeric(1)} | NULL]\cr
# Size of points / lines.
# @return A ggplot object.
# Plot method for a one-dimensional numeric X- or Y-Space
# Here we use geom_density and geom_rug
# And we know both names and short.names have length 1
plot1DNum = function(op, .alpha, .type, log, names, short.names,
space, iter, xlim, colours, ggplot.theme) {
op$.alpha = .alpha
op$.type = .type
if (space == "x") {
title = ggplot2::ggtitle("X-Space")
}
if (space == "y") {
title = ggplot2::ggtitle("Y-Space")
}
pl = ggplot2::ggplot(op, ggplot2::aes(x = .data[[names]]))
pl = pl + ggplot2::geom_density(colour = "black")
pl = pl + title
pl = pl + ggplot2::xlab(short.names)
pl = pl + ggplot2::geom_rug(ggplot2::aes(alpha = .data$.alpha, colour = .data$.type),
sides = "b", linewidth = 2L, data = op)
if (names %in% log) {
pl = pl + ggplot2::coord_trans(xtrans = "log10", limx = xlim)
} else {
pl = pl + ggplot2::coord_cartesian(xlim = xlim)
}
pl = pl + ggplot2::guides(alpha = "none")
pl = pl + ggplot2::scale_alpha_continuous(range = c(max(1 / (iter + 1), 0.1), 1L))
pl = pl + ggplot2::scale_colour_manual(name = "type",
values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L]))
pl = pl + ggplot.theme
return(pl)
}
# Plot method for a one-dimensional discrete X- or Y-Space
# Here we use geom_bar
plot1DDisc = function(op, .alpha, .type, log, names, short.names,
space, iter, ylim, colours, ggplot.theme) {
op$.alpha = as.factor(.alpha)
op$.type = .type
if (space == "x") {
title = ggplot2::ggtitle("X-Space")
}
if (space == "y") {
title = ggplot2::ggtitle("Y-Space")
}
pl = ggplot2::ggplot(op, ggplot2::aes(x = .data[[names[1L]]], fill = .data$.type, alpha = .data$.alpha))
pl = pl + ggplot2::geom_bar()
pl = pl + title
pl = pl + ggplot2::xlab(short.names)
pl = pl + ggplot2::ylim(ylim)
pl = pl + ggplot2::scale_alpha_ordinal(range = c(max(1 / (iter + 1), 0.1), 1L))
pl = pl + ggplot2::scale_fill_manual(name = "type",
values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L]))
pl = pl + ggplot.theme
pl = pl + ggplot2::guides(alpha = "none")
return(pl)
}
# Plot method for a two-dimensional X- or Y-Space
# We use geom_point and jitter for discrete variables
# y.name: we can plot contour-lines for a singel y-variable if both x-variables
# are numeric. in this case, op.y is the data.frame containing the y.variable
plot2D = function(op, .alpha, .type, log, names, short.names, y.name = NULL, op.y = NULL,
space, iter, classes, xlim, ylim, colours, size, ggplot.theme) {
op$.alpha = .alpha
op$.type = .type
if (space == "x") {
title = ggplot2::ggtitle("X-Space")
}
if (space == "y") {
title = ggplot2::ggtitle("Y-Space")
}
if (space == "both") {
title = ggplot2::ggtitle("X- and Y-Space")
}
factor.classes = classes == "factor"
if (any(factor.classes)) {
# Jitter only in the discrete directions
pos = ggplot2::position_jitter(w = 0.1 * factor.classes[1],
h = 0.1 * factor.classes[2])
} else {
pos = "identity"
}
# prepare contour plot
if (!is.null(y.name)) {
requirePackages(c("akima", "reshape2"), why = "renderOptPathPlot plot2D")
fld = with(cbind(op, op.y), akima::interp(x = get(names[1L]), y = get(names[2L]), z = get(y.name)))
df = reshape2::melt(fld$z, na.rm = TRUE)
names(df) = c(names, y.name)
df[[names[1L]]] = fld$x[df[[names[1L]]]]
df[[names[2L]]] = fld$y[df[[names[2L]]]]
}
pl = ggplot2::ggplot()
pl = pl + ggplot2::geom_point(data = op, ggplot2::aes(x = .data[[names[1L]]], y = .data[[names[2L]]],
shape = .data$.type, colour = .data$.type, alpha = .data$.alpha), size = size, position = pos)
# add contour
if (!is.null(y.name)) {
pl = pl + ggplot2::stat_contour(ggplot2::aes(x = .data[[names[1L]]], y = .data[[names[2L]]], z = .data[[y.name]]), data = df)
}
pl = pl + title
pl = pl + ggplot2::xlab(short.names[1L]) + ggplot2::ylab(short.names[2L])
pl = pl + ggplot2::guides(alpha = "none")
pl = pl + ggplot2::scale_colour_manual(name = "type",
values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L]))
pl = pl + ggplot2::scale_shape_manual(name = "type",
values = c(init = 15L, seq = 16L, prop = 17L, marked = 18L))
pl = pl + ggplot2::scale_alpha_continuous(range = c(max(1 / (iter + 1), 0.1), 1L))
pl = pl + ggplot.theme
if (classes[1L] == "numeric") {
if (names[1L] %in% log) {
pl = pl + ggplot2::scale_x_log10(limits = xlim)
} else {
pl = pl + ggplot2::xlim(xlim)
}
}
if (classes[2L] == "numeric") {
if (names[2L] %in% log) {
pl = pl + ggplot2::scale_y_log10(limits = ylim)
} else {
pl = pl + ggplot2::ylim(ylim)
}
}
return(pl)
}
# Plot method for a multi-dimensional X- or Y-Space
# Here we make a PCP using GGally::ggparcoord
plotMultiD = function(op, .alpha, .type, log, names, short.names,
space, iter, colours, size, scale, ggplot.theme) {
args = list(columns = seq_along(names))
# make every variable numeric and check for a log trafo
for (var in names) {
op[, var] = as.numeric(op[, var])
if (var %in% log) {
op[, var] = log10(op[, var])
}
}
op$.alpha = .alpha
# minimal alpha value:
op$.type = .type
args$data = op
args$alphaLines = ".alpha"
args$groupColumn = ncol(op)
args$scale = scale
args$mapping = eval(substitute(ggplot2::aes(linewidth = size), list(size = size)))
if (space == "x") {
title = ggplot2::ggtitle("X-Space")
} else {
title = ggplot2::ggtitle("Y-Space")
}
pl = do.call(GGally::ggparcoord, args)
pl = pl + ggplot2::ylab("scaled values")
pl = pl + ggplot2::scale_x_discrete(labels = short.names)
pl = pl + title
pl = pl + ggplot2::guides(alpha = "none", size = "none")
pl = pl + ggplot2::scale_colour_manual(name = "type",
values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L]))
pl = pl + ggplot.theme
return(pl)
}
# Function to plot one or more numeric variables over time
# names: all corresponding variables must be numeric
# short.names: short names of the variables given by names
multiVariablesOverTime = function(op, .alpha, dob, log, names, short.names,
space, iter, colours, ggplot.theme) {
# For rest variables, we can get a NA data.frame here. In this case, no plot
if (all(is.na(op[, names]))) {
return(NULL)
}
# allow only log trafo of all variables in this plot
log.var = names %in% log
if (any(log.var) && !all(log.var)) {
stop("If you want to apply a log trafo in an over.time.plot, you have to apply it to every variable.")
}
for (var in names) {
if (!is.numeric(op[, var])) {
warning(paste("Converting variable ", var, "to numeric for over time plot."))
}
op[, var] = as.numeric(op[, var])
}
op2 = op[, names]
op2$dob = dob
op2$.alpha = .alpha
# mean over dob
op2 = aggregate(op2, list(op2$dob), mean)[, -1]
# reshape into long format
op2 = reshape(op2, ids = row.names(op2),
times = names, timevar = "variable",
varying = list(names), direction = "long", v.names = c("value"))
pl = ggplot2::ggplot(op2, ggplot2::aes(x = .data$dob, y = .data$value, group = .data$variable,
linetype = .data$variable))
pl = pl + ggplot2::geom_point()
pl = pl + ggplot2::geom_line()
pl = pl + ggplot2::scale_linetype_discrete(labels = short.names)
# For the x axis: only whole numbers as breaks
pl = pl + ggplot2::scale_x_continuous(breaks = function(x) pretty(x, n = min(5, iter + 1)))
# fixed number of decimals:
fmt = function() {
function(x) format(x, nsmall = 3, scientific = FALSE)
}
if (all(log.var)) {
pl = pl + ggplot2::scale_y_log10(labels = fmt())
} else {
pl = pl + ggplot2::scale_y_continuous(labels = fmt())
}
pl = pl + ggplot.theme
return(pl)
}
# Plots One variable versus the DOB. name is the name of the variable to be plotted
oneVariableOverTime = function(op, .alpha, .type, dob, log, names, short.names, iter,
size.points, size.lines, colours, ggplot.theme) {
# For rest variables, we can get a NA data.frame here. In this case, no plot
if (all(is.na(op[, names]))) {
return(NULL)
}
# convert factor variables to numeric
if (!is.numeric(op[, names])) {
warning(paste("Converting variable ", names, "to numeric for over time plot."))
}
op[, names] = as.numeric(op[, names])
# Some data preproc. 2 Different datasets - one for init design, one for rest
op = cbind(op, dob = dob, .alpha = .alpha, .type = .type)
init.des.inds = dob == 0
op.init.des = op[init.des.inds, , drop = FALSE]
op.seq.opt = op[!init.des.inds, , drop = FALSE]
# if we want to log and all values are negative, make them positive.
# this is special treatment for our ei.
if (names %in% log && all(na.omit(op[, names] <= 0))) {
op.init.des[, names] = -op.init.des[, names]
op.seq.opt[, names] = -op.seq.opt[, names]
}
aes.points = ggplot2::aes(x = .data$dob, y = .data[[names]], shape = .data$.type,
colour = .data$.type, alpha = .data$.alpha)
pl = ggplot2::ggplot(op, ggplot2::aes(x = .data$dob, y = .data[[names]]))
# add initial design points allays with jitter in x-direction,
# if discrete also with jitter in y-direction
if (length(na.omit(op.init.des[, names])) > 0L) {
if (is.numeric(op[, names])) {
pl = pl + ggplot2::geom_point(data = op.init.des, mapping = aes.points, size = size.points,
position = ggplot2::position_jitter(height = 0.1))
} else {
pl = pl + ggplot2::geom_point(data = op.init.des, mapping = aes.points, size = size.points,
position = ggplot2::position_jitter(height = 0.1, width = 0.1))
}
}
# add sequential points, if discrete with jitter in y-direction
# Add jitter for discrete variable
if (length(na.omit(op.seq.opt[, names])) > 0L) {
if (is.numeric(op[, names])) {
pl = pl + ggplot2::geom_point(data = op.seq.opt, mapping = aes.points, size = size.points)
} else {
pl = pl + ggplot2::geom_point(data = op.seq.opt, mapping = aes.points, size = size.points,
position = ggplot2::position_jitter(height = 0.1, width = 0.1))
}
# mean data for line plot for sequential data - only for numeric vars
# Also ylims are only useful for numeric vars
if (is.numeric(op[, names])) {
op.seq.means = op.seq.opt[!duplicated(op.seq.opt$dob), ]
op.seq.means[, names] = tapply(op.seq.opt[, names], op.seq.opt[, "dob"], mean)
pl = pl + ggplot2::geom_line(data = op.seq.means, ggplot2::aes(x = .data$dob, y = .data[[names]]), alpha = 0.3)
}
}
# fixed number of decimals:
fmt = function() {
function(x) format(x, nsmall = 3, scientific = FALSE)
}
if (names %in% log) {
pl = pl + ggplot2::scale_y_log10(labels = fmt())
} else {
pl = pl + ggplot2::scale_y_continuous(labels = fmt())
}
pl = pl + ggplot2::geom_vline(xintercept = 0.5)
pl = pl + ggplot2::guides(alpha = "none")
pl = pl + ggplot2::ylab(short.names)
pl = pl + ggplot2::scale_colour_manual(name = "type",
values = c(init = colours[1L], seq = colours[2L], prop = colours[3L], marked = colours[4L]))
pl = pl + ggplot2::scale_shape_manual(name = "type",
values = c(init = 15L, seq = 16L, prop = 17L, marked = 18L))
# set range for alpha scale, so that extra variables (that may not exist in
# iteration 0) will have the same alpha values as all other variables.
range = c(max(min(op$.alpha[!is.na(op[, names])]), 0.1), 1L)
pl = pl + ggplot2::scale_alpha_continuous(range = range)
# For the x axis: only whole numbers as breaks
pl = pl + ggplot2::scale_x_continuous(limits = c(-0.5, NA_real_),
breaks = function(x) pretty(x, n = min(5, iter + 1)))
pl = pl + ggplot.theme
return(pl)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.