Skip to content

Commit

Permalink
deprecated old plot functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
Johan Larsson committed Jan 24, 2018
1 parent 7ddda4b commit 4ad32c4
Show file tree
Hide file tree
Showing 23 changed files with 711 additions and 507 deletions.
12 changes: 7 additions & 5 deletions NEWS.md
Expand Up @@ -3,8 +3,12 @@
## Major changes

* `plot.euler()` has been rewritten completely from scratch, now using
grid graphics directly. As a consequence, all `panel.*()` functions
have been deprecated.
grid graphics directly.
* Arguments `fill`, `fill_alpha`, `auto.key`, `fontface`, `par.settings`,
`default.prepanel`, `default.scales`, and `panel` of `plot.euler()` have
been deprecated.
* All `panel.*()` and `label()` have been deprecated. Their functionality
is in almost all regards available replaced by `plot.euler()`.
* A new argument, `mode`, has been added to `plot.euler()`. It provides
a new method, `mode = "split"` (that is enabled by default),
for plotting the Euler diagram. Using this method, the diagram is
Expand All @@ -17,9 +21,7 @@ Use `mode = "overlay"` to have shapes in the diagram be superposed as before.
`a`, `b`, and `phi`, regardless of which shape is used.

## Minor changes
* `panel.euler.circles()` was deprecated in favor of using
`panel.euler.circles()` as a one-stop solution for all the diagrams.
* Arguments `counts` and `outer_strips` were removed.
* Arguments `counts` and `outer_strips` to `plot.euler()` are now defunct.

# eulerr 3.1.0

Expand Down
186 changes: 112 additions & 74 deletions R/euler.R
Expand Up @@ -37,8 +37,8 @@
#' explored. The stress statistic can also be used as a goodness of fit
#' measure.
#'
#' `euler()` also returns `diagError` and `regionError` from
#' *eulerAPE*. `regionError` is computed as
#' [euler()] also returns `diagError` and `regionError` from
#' \pkg{eulerAPE}. `regionError` is computed as
#'
#' \deqn{
#' \left| \frac{y_i}{\sum y_i} - \frac{\hat{y}_i}{\sum \hat{y}_i}\right|.
Expand All @@ -48,25 +48,25 @@
#'
#' `diagError` is simply the maximum of regionError.
#'
#' @param combinations Set relationships as a named numeric vector, matrix, or
#' data.frame. (See the methods (by class) section for details.)
#' @param by A factor or character matrix to be used in [base::by()] to
#' split the data.frame or matrix of set combinations.
#' @param input The type of input: disjoint class combinations
#' (`disjoint`) or unions (`union`).
#' @param shape The geometric shape used in the diagram: `circle` or `ellipse`.
#' @param control A list of control parameters.
#' * `extraopt`: Should the more thorough optimizer (currently
#' @param combinations set relationships as a named numeric vector, matrix, or
#' data.frame (see **methods (by class)**)
#' @param by a factor or character matrix to be used in [base::by()] to
#' split the data.frame or matrix of set combinations
#' @param input type of input: disjoint identities
#' (`'disjoint'`) or unions (`'union'`).
#' @param shape geometric shape used in the diagram
#' @param control a list of control parameters.
#' * `extraopt`: should the more thorough optimizer (currently
#' [RcppDE::DEoptim()]) kick in (provided `extraopt_threshold` is exceeded)? The
#' default is `TRUE` for ellipses and three sets and `FALSE` otherwise.
#' * `extraopt_threshold`: The threshold, in terms of `diagError`, for when
#' * `extraopt_threshold`: threshold, in terms of `diagError`, for when
#' the extra optimizer kicks in. This will almost always slow down the
#' process considerably. A value of 0 means
#' that the extra optimizer will kick in if there is *any* error. A value of
#' 1 means that it will never kick in. The default is `0.001`.
#' * `extraopt_control`: A list of control parameters to pass to the
#' * `extraopt_control`: a list of control parameters to pass to the
#' extra optimizer, such as `itermax`. See [RcppDE::DEoptim.control()].
#' @param ... Arguments passed down to other methods.
#' @param ... arguments passed down to other methods
#'
#' @return A list object of class `'euler'` with the following parameters.
#' \item{coefficients}{A matrix of `h` and `k` (x and y-coordinates for the
Expand Down Expand Up @@ -100,26 +100,6 @@
#' # Plot it
#' plot(fit2)
#'
#' # A euler diagram from a list of sample spaces (the list method)
#' euler(list(A = c("a", "ab", "ac", "abc"),
#' B = c("b", "ab", "bc", "abc"),
#' C = c("c", "ac", "bc", "abc")))
#'
#' # Using the matrix method
#' mat <- cbind(A = sample(c(TRUE, TRUE, FALSE), size = 50, replace = TRUE),
#' B = sample(c(TRUE, FALSE), size = 50, replace = TRUE))
#' euler(mat)
#'
#' # Using grouping via the 'by' argument
#' dat <- data.frame(
#' A = sample(c(TRUE, FALSE), size = 100, replace = TRUE),
#' B = sample(c(TRUE, TRUE, FALSE), size = 100, replace = TRUE),
#' gender = sample(c("Men", "Women"), size = 100, replace = TRUE),
#' nation = sample(c("Sweden", "Denmark"), size = 100, replace = TRUE)
#' )
#'
#' euler(dat[, 1:2], by = dat[, 3:4])
#'
#' # A set with no perfect solution
#' euler(c("a" = 3491, "b" = 3409, "c" = 3503,
#' "a&b" = 120, "a&c" = 114, "b&c" = 132,
Expand All @@ -138,7 +118,7 @@
#' @export
euler <- function(combinations, ...) UseMethod("euler")

#' @describeIn euler A named numeric vector, with
#' @describeIn euler a named numeric vector, with
#' combinations separated by an ampersand, for instance `A&B = 10`.
#' Missing combinations are treated as being 0.
#'
Expand Down Expand Up @@ -395,59 +375,112 @@ euler.default <- function(
class = c("euler", "list"))
}

#' @describeIn euler A data.frame of logicals, two-level factors (see examples).
#' @param weights A numeric vector of weights of the same length as `by` and
#' @describeIn euler a data.frame of logicals, two-level factors (see examples).
#' @param weights a numeric vector of weights of the same length as `by` and
#' the number of rows in `combinations`.
#' @export
#' @examples
#' # Using grouping via the 'by' argument through the data.frame method
#' dat <- data.frame(
#' A = sample(c(TRUE, FALSE), size = 100, replace = TRUE),
#' B = sample(c(TRUE, TRUE, FALSE), size = 100, replace = TRUE),
#' gender = sample(c("Men", "Women"), size = 100, replace = TRUE),
#' nation = sample(c("Sweden", "Denmark"), size = 100, replace = TRUE)
#' )
#'
#' euler(dat, by = list(gender, nation))
euler.data.frame <- function(combinations, weights = NULL, by = NULL, ...) {
stopifnot(!any(grepl("&", colnames(combinations), fixed = TRUE)))

if (is.null(weights))
weights <- rep.int(1L, nrow(combinations))
facs <- eval(substitute(by), combinations)

if (!is.null(by)) {
stopifnot(all(vapply(by,
function(x) (is.factor(x) || is.character(x)),
FUN.VALUE = logical(1))))
if (NCOL(by) > 2L)
stop("No more than two conditioning variables are allowed.")
}
if (!is.null(facs)) {
if (is.list(facs)) {
if (!is.null(names(facs)))
nms <- names(facs)
else {
nms <- sapply(substitute(by)[-1L], deparse)
}
} else
nms <- deparse(substitute(by))

if (is.list(facs))
stopifnot(length(facs) < 3)
else
facs <- list(facs)

dd <- as.data.frame(facs, col.names = nms)
groups <- unique(dd)
rownames(groups) <- NULL

out <- g <- vector("list", NROW(groups))
int_or_log <- vapply(combinations,
function(x) is.numeric(x) || is.logical(x),
FUN.VALUE = logical(1L))
for (i in seq_len(NROW(groups))) {
ind <- apply(dd, 1, function(x) all(x == groups[i, ]))
out[[i]] <- euler(combinations[ind, int_or_log])
names(out)[[i]] <- paste(unlist(groups[i, , drop = TRUE]),
collapse = ".")
}

out <- matrix(NA, nrow = nrow(combinations), ncol = ncol(combinations))
colnames(out) <- colnames(combinations)

for (i in seq_along(combinations)) {
y <- combinations[, i]
if (is.factor(y) || is.character(y)) {
facs <- unique(as.character(y))
if (length(facs) > 2L)
stop("No more than 2 levels allowed.")
out[, i] <- y == facs[1L]
colnames(out)[i] <- facs[1L]
} else if (is.numeric(y)) {
out[, i] <- as.logical(y)
} else if (is.logical(y)) {
out[, i] <- y
class(out) <- c("euler", "list")
attr(out, "groups") <- groups
} else {
if (is.null(weights)) {
combinations <- combinations[,
vapply(combinations,
function(y)
is.integer(y) || is.logical(y),
FUN.VALUE = logical(1L))]
} else {
stop("Unsupported type of variables.")
combinations <- combinations[,
vapply(combinations,
function(y)
is.integer(y) ||
is.logical(y) ||
is.factor(y) ||
is.character(y),
FUN.VALUE = logical(1L))]
}
}
combinations <- as.data.frame(out)
combinations$weights <- weights

if (is.null(by)) {
out <- tally_combinations(combinations)
} else {
out <- by(combinations, by, tally_combinations, simplify = FALSE)
class(out) <- c("by", "euler", "list")
if (is.null(weights))
weights <- rep.int(1L, NROW(combinations))

out <- matrix(NA, nrow = NROW(combinations), ncol = NCOL(combinations))
colnames(out) <- colnames(combinations)

for (i in seq_along(combinations)) {
y <- combinations[, i]
if (is.factor(y) || is.character(y)) {
facs <- unique(as.character(y))
if (length(facs) > 2L)
stop("no more than 2 levels allowed")
out[, i] <- y == facs[1L]
colnames(out)[i] <- facs[1L]
} else if (is.numeric(y)) {
out[, i] <- as.logical(y)
} else if (is.logical(y)) {
out[, i] <- y
} else {
stop("unsupported type of variables")
}
}
combinations <- as.data.frame(out)
out <- tally_combinations(combinations, weights)
out <- euler(out, ...)
}

out
}

#' @describeIn euler A matrix that can be converted to a data.frame of logicals
#' @describeIn euler a matrix that can be converted to a data.frame of logicals
#' (as in the description above) via [base::as.data.frame.matrix()].
#' @export
#' @examples
#' # Using the matrix method
#' mat <- cbind(A = sample(c(TRUE, TRUE, FALSE), size = 50, replace = TRUE),
#' B = sample(c(TRUE, FALSE), size = 50, replace = TRUE))
#' euler(mat)
euler.matrix <- function(combinations, ...) {
euler(as.data.frame(combinations), ...)
}
Expand All @@ -459,14 +492,19 @@ euler.matrix <- function(combinations, ...) {
#' plot(euler(as.table(apply(Titanic, 2:4, sum))))
euler.table <- function(combinations, ...) {
if (max(dim(combinations)) > 2L)
stop("No table dimension may exceed 2.")
stop("no table dimension may exceed 2")
x <- as.data.frame(combinations)
euler(x[, !(names(x) == "Freq")], weights = x$Freq, ...)
}

#' @describeIn euler A list of vectors, each vector giving the contents of
#' @describeIn euler a list of vectors, each vector giving the contents of
#' that set (with no duplicates). Vectors in the list do not need to be named.
#' @export
#' @examples
#' # A euler diagram from a list of sample spaces (the list method)
#' euler(list(A = c("a", "ab", "ac", "abc"),
#' B = c("b", "ab", "bc", "abc"),
#' C = c("c", "ac", "bc", "abc")))
euler.list <- function(combinations, ...) {
stopifnot(!is.null(attr(combinations, "names")),
!any(names(combinations) == ""),
Expand Down
10 changes: 4 additions & 6 deletions R/eulerr-deprecated.R
Expand Up @@ -273,8 +273,10 @@ panel.euler.circles <- function(x,
#' @return Plots ellipses inside a trellis panel.
#'
#' @name panel.euler.ellipses-deprecated
#' @usage panel.euler.ellipses(x, y, ra, rb, phi, fill, fill_alpha, border, ...,
#' mode, identifier, n, fitted.values, ..., name.type, col, font, fontface)
#' @usage panel.euler.ellipses(x, y, ra, rb, phi, fill = "transparent",
#' fill_alpha = 0.4, border = "black", mode = c("split", "overlay"),
#' identifier = NULL, n = 200, fitted.values, ..., name.type = "panel",
#' col, font, fontface)
#' @seealso [eulerr-deprecated]
#' @keywords internal
NULL
Expand Down Expand Up @@ -508,10 +510,6 @@ panel.euler.labels <- function(x,
#' @return A numeric matrix of x and y coordinates for the labels, as well as
#' the quantities and proportions for the overlaps depicted in the labels.
#'
#' @examples
#' fit <- euler(c(A = 1, B = 3, "A&B" = 0.9))
#' label(fit)
#'
#' @name label-deprecated
#' @usage label(x, labels)
#' @seealso [eulerr-deprecated]
Expand Down

0 comments on commit 4ad32c4

Please sign in to comment.