From ad44f43371291eb5cf4a740bb78d60cb595650dc Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 15:13:42 +0900 Subject: [PATCH 1/8] Replace unhighlighted_colour param with unhighligted_aes --- DESCRIPTION | 2 +- R/gghighlight.R | 28 ++++++++++++++++++---------- man/gghighlight-old.Rd | 12 ++++++------ man/gghighlight.Rd | 10 ++++++---- tests/testthat/test-gghighlight.R | 14 +++++++------- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 71237c5..c2c6054 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,7 +22,7 @@ Imports: rlang LazyData: true Roxygen: list(markdown = TRUE) -RoxygenNote: 6.0.1.9000 +RoxygenNote: 6.1.1 Suggests: testthat, knitr, diff --git a/R/gghighlight.R b/R/gghighlight.R index a55be8e..04d0e29 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -10,8 +10,8 @@ #' Number of layers to clone. #' @param max_highlight #' Max number of series to highlight. -#' @param unhighlighted_colour -#' Colour for unhighlighted geoms. +#' @param unhighlighted_aes +#' Aesthetics (e.g. colour, fill, and size) for unhighlighted geoms. #' @param use_group_by #' If `TRUE`, use [dplyr::group_by()] to evaluate `predicate`. #' @param use_direct_label @@ -20,6 +20,8 @@ #' Column name for `label` aesthetics. #' @param label_params #' A list of parameters, which is passed to [ggrepel::geom_label_repel()]. +#' @param unhighlighted_colour +#' (Deprecated) Colour for unhighlighted geoms. #' #' @examples #' d <- data.frame( @@ -42,11 +44,12 @@ gghighlight <- function(..., n = NULL, max_highlight = 5L, - unhighlighted_colour = ggplot2::alpha("grey", 0.7), + unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7)), use_group_by = NULL, use_direct_label = NULL, label_key = NULL, - label_params = list(fill = "white")) { + label_params = list(fill = "white"), + unhighlighted_colour = NULL) { # if use_direct_label is NULL, try to use direct labels but ignore failures # if use_direct_label is TRUE, use direct labels, otherwise stop() @@ -57,12 +60,17 @@ gghighlight <- function(..., label_key_must_exist <- FALSE } + if (!is.null(unhighlighted_colour)) { + rlang::warn("unhighlighted_colour is deprecated. Use unhighlighted_aes instead.") + unhighlighted_aes$colour <- unhighlighted_colour + } + structure( list( predicates = rlang::enquos(...), n = n, max_highlight = max_highlight, - unhighlighted_colour = unhighlighted_colour, + unhighlighted_aes = unhighlighted_aes, use_group_by = use_group_by, use_direct_label = use_direct_label, label_key_must_exist = label_key_must_exist, @@ -115,7 +123,7 @@ ggplot_add.gg_highlighter <- function(object, plot, object_name) { layers_bleached, group_infos, bleach_layer, - unhighlighted_colour = object$unhighlighted_colour + unhighlighted_aes = object$unhighlighted_aes ) # Sieve the upper layer. @@ -216,14 +224,14 @@ calculate_group_info <- function(data, mapping) { } bleach_layer <- function(layer, group_info, - unhighlighted_colour = ggplot2::alpha("grey", 0.7)) { + unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7))) { # Set colour and fill to grey when it is included in the mappping. # But, if the default_aes is NA, respect it. # (Note that this needs to be executed before modifying the layer$mapping) params_bleached <- purrr::map( rlang::set_names(c("colour", "fill")), choose_bleached_colour, - geom = layer$geom, mapping = layer$mapping, bleached_colour = unhighlighted_colour + geom = layer$geom, mapping = layer$mapping, bleached_aes = unhighlighted_aes ) params_bleached <- purrr::compact(params_bleached) layer$aes_params <- utils::modifyList(layer$aes_params, params_bleached) @@ -252,7 +260,7 @@ bleach_layer <- function(layer, group_info, layer } -choose_bleached_colour <- function(aes_name, geom, mapping, bleached_colour) { +choose_bleached_colour <- function(aes_name, geom, mapping, bleached_aes) { if (!aes_name %in% geom$aesthetics()) { return(NULL) } @@ -262,7 +270,7 @@ choose_bleached_colour <- function(aes_name, geom, mapping, bleached_colour) { is.na(geom$default_aes[aes_name])) { return(NA) } - return(bleached_colour) + return(bleached_aes$colour) } sieve_layer <- function(layer, group_info, predicates, diff --git a/man/gghighlight-old.Rd b/man/gghighlight-old.Rd index 1d8d12e..3e5da21 100644 --- a/man/gghighlight-old.Rd +++ b/man/gghighlight-old.Rd @@ -7,14 +7,14 @@ \title{Highlight Data With Predicate} \usage{ gghighlight_line(data, mapping, predicate, max_highlight = 5L, - unhighlighted_colour = ggplot2::alpha("grey", 0.7), use_group_by = TRUE, - use_direct_label = TRUE, label_key = NULL, ..., - environment = parent.frame()) + unhighlighted_colour = ggplot2::alpha("grey", 0.7), + use_group_by = TRUE, use_direct_label = TRUE, label_key = NULL, + ..., environment = parent.frame()) gghighlight_point(data, mapping, predicate, max_highlight = 5L, - unhighlighted_colour = ggplot2::alpha("grey", 0.7), use_group_by = FALSE, - use_direct_label = TRUE, label_key = NULL, ..., - environment = parent.frame()) + unhighlighted_colour = ggplot2::alpha("grey", 0.7), + use_group_by = FALSE, use_direct_label = TRUE, label_key = NULL, + ..., environment = parent.frame()) } \arguments{ \item{data}{Default dataset to use for plot. If not already a data.frame, diff --git a/man/gghighlight.Rd b/man/gghighlight.Rd index a171878..ac991a8 100644 --- a/man/gghighlight.Rd +++ b/man/gghighlight.Rd @@ -5,9 +5,9 @@ \title{Highlight Data With Predicate} \usage{ gghighlight(..., n = NULL, max_highlight = 5L, - unhighlighted_colour = ggplot2::alpha("grey", 0.7), use_group_by = NULL, - use_direct_label = NULL, label_key = NULL, label_params = list(fill = - "white")) + unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7)), + use_group_by = NULL, use_direct_label = NULL, label_key = NULL, + label_params = list(fill = "white"), unhighlighted_colour = NULL) } \arguments{ \item{...}{Expressions to filter data, which is passed to \code{\link[dplyr:filter]{dplyr::filter()}}.} @@ -16,7 +16,7 @@ gghighlight(..., n = NULL, max_highlight = 5L, \item{max_highlight}{Max number of series to highlight.} -\item{unhighlighted_colour}{Colour for unhighlighted geoms.} +\item{unhighlighted_aes}{Aesthetics (e.g. colour, fill, and size) for unhighlighted geoms.} \item{use_group_by}{If \code{TRUE}, use \code{\link[dplyr:group_by]{dplyr::group_by()}} to evaluate \code{predicate}.} @@ -25,6 +25,8 @@ gghighlight(..., n = NULL, max_highlight = 5L, \item{label_key}{Column name for \code{label} aesthetics.} \item{label_params}{A list of parameters, which is passed to \code{\link[ggrepel:geom_label_repel]{ggrepel::geom_label_repel()}}.} + +\item{unhighlighted_colour}{(Deprecated) Colour for unhighlighted geoms.} } \description{ \code{gghiglight()} highlights (almost) any geoms according to the given predicates. diff --git a/tests/testthat/test-gghighlight.R b/tests/testthat/test-gghighlight.R index ba28a7e..ca70b57 100644 --- a/tests/testthat/test-gghighlight.R +++ b/tests/testthat/test-gghighlight.R @@ -88,30 +88,30 @@ aes_bleached <- aes_string(x = paste0(prefix, 1), test_that("bleach_layer() works", { # If colour is specified, colour is used as the group key. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, list(colour = grey07)), geom_line(aes_bleached, d_bleached, colour = grey07)) # If colour is specified but group_key is NULL, the result is the same data. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, grey07), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, list(colour = grey07)), geom_line(aes(colour = NULL, fill = NULL), d, colour = grey07)) # If the geom accepts fill, it is sets to grey even when it is not included in the mapping. - expect_equal_layer(bleach_layer(geom_bar(aes(colour = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_bar(aes(colour = type), d), g_info, list(colour = grey07)), geom_bar(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If the default of colour of the geom is NA and mapping doesn't specify it, params will be NA. - expect_equal_layer(bleach_layer(geom_bar(aes(fill = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_bar(aes(fill = type), d), g_info, list(colour = grey07)), geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) # If colour and fill is specified at the same time, fill is used as the group key. - expect_equal_layer(bleach_layer(geom_bar(aes(colour = type, fill = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_bar(aes(colour = type, fill = type), d), g_info, list(colour = grey07)), geom_bar(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If mapping doesn't have colour or fill, group or x aes can be used as group key. # c.f. https://github.com/yutannihilation/gghighlight/pull/17#issuecomment-390486101. - expect_equal_layer(bleach_layer(geom_bar(aes(group = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_bar(aes(group = type), d), g_info, list(colour = grey07)), geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) - expect_equal_layer(bleach_layer(geom_bar(aes(x = type), d), g_info, grey07), + expect_equal_layer(bleach_layer(geom_bar(aes(x = type), d), g_info, list(colour = grey07)), geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) }) From a00cc15bb81844ed8deac250b472da683b52df62 Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 17:10:30 +0900 Subject: [PATCH 2/8] Normalize unhighlighted_aes --- R/gghighlight.R | 30 +++++++++++++++++++++++++--- tests/testthat/test-gghighlight.R | 33 ++++++++++++++++++++----------- tests/testthat/test-internals.R | 26 ++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/R/gghighlight.R b/R/gghighlight.R index 04d0e29..5049fd9 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -60,6 +60,9 @@ gghighlight <- function(..., label_key_must_exist <- FALSE } + # if fill is not specified, use colour for fill, or vice versa + unhighlighted_aes <- normalize_unhighlighted_aes(unhighlighted_aes) + if (!is.null(unhighlighted_colour)) { rlang::warn("unhighlighted_colour is deprecated. Use unhighlighted_aes instead.") unhighlighted_aes$colour <- unhighlighted_colour @@ -223,8 +226,8 @@ calculate_group_info <- function(data, mapping) { } } -bleach_layer <- function(layer, group_info, - unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7))) { +bleach_layer <- function(layer, group_info, unhighlighted_aes) { + # Set colour and fill to grey when it is included in the mappping. # But, if the default_aes is NA, respect it. # (Note that this needs to be executed before modifying the layer$mapping) @@ -270,7 +273,7 @@ choose_bleached_colour <- function(aes_name, geom, mapping, bleached_aes) { is.na(geom$default_aes[aes_name])) { return(NA) } - return(bleached_aes$colour) + return(bleached_aes[[aes_name]]) } sieve_layer <- function(layer, group_info, predicates, @@ -373,3 +376,24 @@ choose_col_for_filter_and_arrange <- function(data, exclude_col) { arrange = rlang::syms(names(data)[!col_idx_lgl & !col_idx_lst]) ) } + +normalize_unhighlighted_aes <- function(aes_params) { + if (!is.list(aes_params)) { + rlang::abort("unhighlighted_aes must be a list.") + } + + # color is an alias of colour + if (!is.null(aes_params$color)) { + aes_params$colour <- aes_params$colour %||% aes_params$color + aes_params$color <- NULL + } + + # if fill or colour is missing, use the other for it + if (is.null(aes_params$colour) && is.null(aes_params$fill)) { + rlang::abort("unhighlighted_aes must contain at least either of colour or fill.") + } + + aes_params$colour <- aes_params$colour %||% aes_params$fill + aes_params$fill <- aes_params$fill %||% aes_params$colour + aes_params +} diff --git a/tests/testthat/test-gghighlight.R b/tests/testthat/test-gghighlight.R index ca70b57..cb4980e 100644 --- a/tests/testthat/test-gghighlight.R +++ b/tests/testthat/test-gghighlight.R @@ -2,6 +2,7 @@ context("test-gghighlight.R") library(ggplot2) grey07 <- ggplot2::alpha("grey", 0.7) +grey09 <- ggplot2::alpha("grey", 0.9) d <- tibble::tribble( ~x, ~y, ~type, ~value, @@ -87,32 +88,40 @@ aes_bleached <- aes_string(x = paste0(prefix, 1), group = paste0(prefix, "group")) test_that("bleach_layer() works", { + aes_grey07 <- normalize_unhighlighted_aes(list(colour = grey07)) + # If colour is specified, colour is used as the group key. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, list(colour = grey07)), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, aes_grey07), geom_line(aes_bleached, d_bleached, colour = grey07)) # If colour is specified but group_key is NULL, the result is the same data. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, list(colour = grey07)), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, aes_grey07), geom_line(aes(colour = NULL, fill = NULL), d, colour = grey07)) # If the geom accepts fill, it is sets to grey even when it is not included in the mapping. - expect_equal_layer(bleach_layer(geom_bar(aes(colour = type), d), g_info, list(colour = grey07)), - geom_bar(aes_bleached, d_bleached, colour = grey07, fill = grey07)) + expect_equal_layer(bleach_layer(geom_col(aes(colour = type), d), g_info, aes_grey07), + geom_col(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If the default of colour of the geom is NA and mapping doesn't specify it, params will be NA. - expect_equal_layer(bleach_layer(geom_bar(aes(fill = type), d), g_info, list(colour = grey07)), - geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) + expect_equal_layer(bleach_layer(geom_col(aes(fill = type), d), g_info, aes_grey07), + geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) # If colour and fill is specified at the same time, fill is used as the group key. - expect_equal_layer(bleach_layer(geom_bar(aes(colour = type, fill = type), d), g_info, list(colour = grey07)), - geom_bar(aes_bleached, d_bleached, colour = grey07, fill = grey07)) + expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, aes_grey07), + geom_col(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If mapping doesn't have colour or fill, group or x aes can be used as group key. # c.f. https://github.com/yutannihilation/gghighlight/pull/17#issuecomment-390486101. - expect_equal_layer(bleach_layer(geom_bar(aes(group = type), d), g_info, list(colour = grey07)), - geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) - expect_equal_layer(bleach_layer(geom_bar(aes(x = type), d), g_info, list(colour = grey07)), - geom_bar(aes_bleached, d_bleached, colour = NA, fill = grey07)) + expect_equal_layer(bleach_layer(geom_col(aes(group = type), d), g_info, aes_grey07), + geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) + expect_equal_layer(bleach_layer(geom_col(aes(x = type), d), g_info, aes_grey07), + geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) + + # unhighlighted_aes can be more detailed + aes_grey07_and_more <- normalize_unhighlighted_aes(list(colour = grey09, fill = grey07, width = 0.5)) + + expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, aes_grey07_and_more), + geom_col(aes_bleached, d_bleached, colour = grey09, fill = grey07, width = 0.5)) }) test_that("sieve_layer() works with simple cases", { diff --git a/tests/testthat/test-internals.R b/tests/testthat/test-internals.R index 150550f..ef85780 100644 --- a/tests/testthat/test-internals.R +++ b/tests/testthat/test-internals.R @@ -15,3 +15,29 @@ test_that("choose_col_for_filter_and_arrange() works", { expect_equal(choose_col_for_filter_and_arrange(d1, rlang::quo(x)), !!expected) }) + +test_that("normalize_unhighlighted_aes() works", { + expect_listequal <- function(x, y) { + expect_equal(!!x[sort(names(x))], !!y[sort(names(y))]) + } + + # if fill or colour is missing, use the other for it + expect_listequal(normalize_unhighlighted_aes(list(colour = "red")), + list(colour = "red", fill = "red")) + expect_listequal(normalize_unhighlighted_aes(list(fill = "red")), + list(colour = "red", fill = "red")) + # if fill and colour is specified, respect both + expect_listequal(normalize_unhighlighted_aes(list(colour = "blue", fill = "red")), + list(colour = "blue", fill = "red")) + # other parameters are left as is + expect_listequal(normalize_unhighlighted_aes(list(fill = "red", size = 0.2)), + list(colour = "red", fill = "red", size = 0.2)) + # color is an alias of colour + expect_listequal(normalize_unhighlighted_aes(list(color = "red")), + list(colour = "red", fill = "red")) + # if both colour and color are specified, use colour. + expect_listequal(normalize_unhighlighted_aes(list(colour = "blue", color = "red")), + list(colour = "blue", fill = "blue")) + # if both fill and colour are missing, raise error + expect_error(normalize_unhighlighted_aes(list())) +}) From 2646f539adca7a1afe547444a820720ed51e11e5 Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 18:06:35 +0900 Subject: [PATCH 3/8] Consider geom_params --- R/gghighlight.R | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/R/gghighlight.R b/R/gghighlight.R index 5049fd9..de4eae5 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -228,16 +228,17 @@ calculate_group_info <- function(data, mapping) { bleach_layer <- function(layer, group_info, unhighlighted_aes) { - # Set colour and fill to grey when it is included in the mappping. - # But, if the default_aes is NA, respect it. + # c.f. https://github.com/tidyverse/ggplot2/blob/e9d4e5dd599b9f058cbe9230a6517f85f3587567/R/layer.r#L107-L108 + aes_params_bleached <- unhighlighted_aes[names(unhighlighted_aes) %in% layer$geom$aesthetics()] + geom_params_bleached <- unhighlighted_aes[names(unhighlighted_aes) %in% layer$geom$parameters(TRUE)] + + # Use the colour and fill specified in unhighlighted_aes when it is included in + # the mappping. But, if the default_aes is NA, respect it. # (Note that this needs to be executed before modifying the layer$mapping) - params_bleached <- purrr::map( - rlang::set_names(c("colour", "fill")), - choose_bleached_colour, - geom = layer$geom, mapping = layer$mapping, bleached_aes = unhighlighted_aes - ) - params_bleached <- purrr::compact(params_bleached) - layer$aes_params <- utils::modifyList(layer$aes_params, params_bleached) + aes_params_bleached <- fill_unhighlighted_aes_with_na(aes_params_bleached, layer$geom, layer$mapping) + + layer$aes_params <- utils::modifyList(layer$aes_params, aes_params_bleached) + layer$geom_params <- utils::modifyList(layer$geom_params, geom_params_bleached) # remove colour and fill from mapping layer$mapping[c("colour", "fill")] <- list(NULL) @@ -263,17 +264,17 @@ bleach_layer <- function(layer, group_info, unhighlighted_aes) { layer } -choose_bleached_colour <- function(aes_name, geom, mapping, bleached_aes) { - if (!aes_name %in% geom$aesthetics()) { - return(NULL) - } - # if aes_name is specified in the mapping, it should be bleached. - if (!aes_name %in% names(mapping) && - aes_name %in% names(geom$default_aes) && - is.na(geom$default_aes[aes_name])) { - return(NA) - } - return(bleached_aes[[aes_name]]) +fill_unhighlighted_aes_with_na <- function(unhighlighted_aes, geom, mapping) { + aes_name <- names(unhighlighted_aes) + + # if aes_name is not specified in the mapping and the default_aes is NA, use NA. + is_default_na <- !aes_name %in% names(mapping) & + aes_name %in% names(geom$default_aes) & + is.na(geom$default_aes[aes_name]) + + unhighlighted_aes[is_default_na] <- NA + + unhighlighted_aes } sieve_layer <- function(layer, group_info, predicates, From 28608bf7e2be2e762fa6f96d735b44fff4700109 Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 18:17:06 +0900 Subject: [PATCH 4/8] Fill default values --- R/gghighlight.R | 7 +++++-- tests/testthat/test-internals.R | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/R/gghighlight.R b/R/gghighlight.R index de4eae5..9e2e296 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -389,11 +389,14 @@ normalize_unhighlighted_aes <- function(aes_params) { aes_params$color <- NULL } - # if fill or colour is missing, use the other for it + # if both fill and colour are missing, use the default value if (is.null(aes_params$colour) && is.null(aes_params$fill)) { - rlang::abort("unhighlighted_aes must contain at least either of colour or fill.") + aes_params$colour <- ggplot2::alpha("grey", 0.7) + aes_params$fill <- ggplot2::alpha("grey", 0.7) + return(aes_params) } + # if fill or colour is missing, use the other for it aes_params$colour <- aes_params$colour %||% aes_params$fill aes_params$fill <- aes_params$fill %||% aes_params$colour aes_params diff --git a/tests/testthat/test-internals.R b/tests/testthat/test-internals.R index ef85780..71ed174 100644 --- a/tests/testthat/test-internals.R +++ b/tests/testthat/test-internals.R @@ -39,5 +39,6 @@ test_that("normalize_unhighlighted_aes() works", { expect_listequal(normalize_unhighlighted_aes(list(colour = "blue", color = "red")), list(colour = "blue", fill = "blue")) # if both fill and colour are missing, raise error - expect_error(normalize_unhighlighted_aes(list())) + expect_listequal(normalize_unhighlighted_aes(list()), + list(colour = ggplot2::alpha("grey", 0.7), fill = ggplot2::alpha("grey", 0.7))) }) From f019ad99c4434ce74f88438b9c60a7979c72666d Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 18:19:17 +0900 Subject: [PATCH 5/8] Rename unhighlighted_aes to unhighlighted_params --- R/gghighlight.R | 36 +++++++++++++++---------------- man/gghighlight.Rd | 4 ++-- tests/testthat/test-gghighlight.R | 6 +++--- tests/testthat/test-internals.R | 16 +++++++------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/R/gghighlight.R b/R/gghighlight.R index 9e2e296..41ada89 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -10,7 +10,7 @@ #' Number of layers to clone. #' @param max_highlight #' Max number of series to highlight. -#' @param unhighlighted_aes +#' @param unhighlighted_params #' Aesthetics (e.g. colour, fill, and size) for unhighlighted geoms. #' @param use_group_by #' If `TRUE`, use [dplyr::group_by()] to evaluate `predicate`. @@ -44,7 +44,7 @@ gghighlight <- function(..., n = NULL, max_highlight = 5L, - unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7)), + unhighlighted_params = list(colour = ggplot2::alpha("grey", 0.7)), use_group_by = NULL, use_direct_label = NULL, label_key = NULL, @@ -61,11 +61,11 @@ gghighlight <- function(..., } # if fill is not specified, use colour for fill, or vice versa - unhighlighted_aes <- normalize_unhighlighted_aes(unhighlighted_aes) + unhighlighted_params <- normalize_unhighlighted_params(unhighlighted_params) if (!is.null(unhighlighted_colour)) { - rlang::warn("unhighlighted_colour is deprecated. Use unhighlighted_aes instead.") - unhighlighted_aes$colour <- unhighlighted_colour + rlang::warn("unhighlighted_colour is deprecated. Use unhighlighted_params instead.") + unhighlighted_params$colour <- unhighlighted_colour } structure( @@ -73,7 +73,7 @@ gghighlight <- function(..., predicates = rlang::enquos(...), n = n, max_highlight = max_highlight, - unhighlighted_aes = unhighlighted_aes, + unhighlighted_params = unhighlighted_params, use_group_by = use_group_by, use_direct_label = use_direct_label, label_key_must_exist = label_key_must_exist, @@ -126,7 +126,7 @@ ggplot_add.gg_highlighter <- function(object, plot, object_name) { layers_bleached, group_infos, bleach_layer, - unhighlighted_aes = object$unhighlighted_aes + unhighlighted_params = object$unhighlighted_params ) # Sieve the upper layer. @@ -226,16 +226,16 @@ calculate_group_info <- function(data, mapping) { } } -bleach_layer <- function(layer, group_info, unhighlighted_aes) { +bleach_layer <- function(layer, group_info, unhighlighted_params) { # c.f. https://github.com/tidyverse/ggplot2/blob/e9d4e5dd599b9f058cbe9230a6517f85f3587567/R/layer.r#L107-L108 - aes_params_bleached <- unhighlighted_aes[names(unhighlighted_aes) %in% layer$geom$aesthetics()] - geom_params_bleached <- unhighlighted_aes[names(unhighlighted_aes) %in% layer$geom$parameters(TRUE)] + aes_params_bleached <- unhighlighted_params[names(unhighlighted_params) %in% layer$geom$aesthetics()] + geom_params_bleached <- unhighlighted_params[names(unhighlighted_params) %in% layer$geom$parameters(TRUE)] - # Use the colour and fill specified in unhighlighted_aes when it is included in + # Use the colour and fill specified in unhighlighted_params when it is included in # the mappping. But, if the default_aes is NA, respect it. # (Note that this needs to be executed before modifying the layer$mapping) - aes_params_bleached <- fill_unhighlighted_aes_with_na(aes_params_bleached, layer$geom, layer$mapping) + aes_params_bleached <- fill_unhighlighted_params_with_na(aes_params_bleached, layer$geom, layer$mapping) layer$aes_params <- utils::modifyList(layer$aes_params, aes_params_bleached) layer$geom_params <- utils::modifyList(layer$geom_params, geom_params_bleached) @@ -264,17 +264,17 @@ bleach_layer <- function(layer, group_info, unhighlighted_aes) { layer } -fill_unhighlighted_aes_with_na <- function(unhighlighted_aes, geom, mapping) { - aes_name <- names(unhighlighted_aes) +fill_unhighlighted_params_with_na <- function(unhighlighted_params, geom, mapping) { + aes_name <- names(unhighlighted_params) # if aes_name is not specified in the mapping and the default_aes is NA, use NA. is_default_na <- !aes_name %in% names(mapping) & aes_name %in% names(geom$default_aes) & is.na(geom$default_aes[aes_name]) - unhighlighted_aes[is_default_na] <- NA + unhighlighted_params[is_default_na] <- NA - unhighlighted_aes + unhighlighted_params } sieve_layer <- function(layer, group_info, predicates, @@ -378,9 +378,9 @@ choose_col_for_filter_and_arrange <- function(data, exclude_col) { ) } -normalize_unhighlighted_aes <- function(aes_params) { +normalize_unhighlighted_params <- function(aes_params) { if (!is.list(aes_params)) { - rlang::abort("unhighlighted_aes must be a list.") + rlang::abort("unhighlighted_params must be a list.") } # color is an alias of colour diff --git a/man/gghighlight.Rd b/man/gghighlight.Rd index ac991a8..dc8fdef 100644 --- a/man/gghighlight.Rd +++ b/man/gghighlight.Rd @@ -5,7 +5,7 @@ \title{Highlight Data With Predicate} \usage{ gghighlight(..., n = NULL, max_highlight = 5L, - unhighlighted_aes = list(colour = ggplot2::alpha("grey", 0.7)), + unhighlighted_params = list(colour = ggplot2::alpha("grey", 0.7)), use_group_by = NULL, use_direct_label = NULL, label_key = NULL, label_params = list(fill = "white"), unhighlighted_colour = NULL) } @@ -16,7 +16,7 @@ gghighlight(..., n = NULL, max_highlight = 5L, \item{max_highlight}{Max number of series to highlight.} -\item{unhighlighted_aes}{Aesthetics (e.g. colour, fill, and size) for unhighlighted geoms.} +\item{unhighlighted_params}{Aesthetics (e.g. colour, fill, and size) for unhighlighted geoms.} \item{use_group_by}{If \code{TRUE}, use \code{\link[dplyr:group_by]{dplyr::group_by()}} to evaluate \code{predicate}.} diff --git a/tests/testthat/test-gghighlight.R b/tests/testthat/test-gghighlight.R index cb4980e..c4076de 100644 --- a/tests/testthat/test-gghighlight.R +++ b/tests/testthat/test-gghighlight.R @@ -88,7 +88,7 @@ aes_bleached <- aes_string(x = paste0(prefix, 1), group = paste0(prefix, "group")) test_that("bleach_layer() works", { - aes_grey07 <- normalize_unhighlighted_aes(list(colour = grey07)) + aes_grey07 <- normalize_unhighlighted_params(list(colour = grey07)) # If colour is specified, colour is used as the group key. expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, aes_grey07), @@ -117,8 +117,8 @@ test_that("bleach_layer() works", { expect_equal_layer(bleach_layer(geom_col(aes(x = type), d), g_info, aes_grey07), geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) - # unhighlighted_aes can be more detailed - aes_grey07_and_more <- normalize_unhighlighted_aes(list(colour = grey09, fill = grey07, width = 0.5)) + # unhighlighted_params can be more detailed + aes_grey07_and_more <- normalize_unhighlighted_params(list(colour = grey09, fill = grey07, width = 0.5)) expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, aes_grey07_and_more), geom_col(aes_bleached, d_bleached, colour = grey09, fill = grey07, width = 0.5)) diff --git a/tests/testthat/test-internals.R b/tests/testthat/test-internals.R index 71ed174..27b9511 100644 --- a/tests/testthat/test-internals.R +++ b/tests/testthat/test-internals.R @@ -16,29 +16,29 @@ test_that("choose_col_for_filter_and_arrange() works", { !!expected) }) -test_that("normalize_unhighlighted_aes() works", { +test_that("normalize_unhighlighted_params() works", { expect_listequal <- function(x, y) { expect_equal(!!x[sort(names(x))], !!y[sort(names(y))]) } # if fill or colour is missing, use the other for it - expect_listequal(normalize_unhighlighted_aes(list(colour = "red")), + expect_listequal(normalize_unhighlighted_params(list(colour = "red")), list(colour = "red", fill = "red")) - expect_listequal(normalize_unhighlighted_aes(list(fill = "red")), + expect_listequal(normalize_unhighlighted_params(list(fill = "red")), list(colour = "red", fill = "red")) # if fill and colour is specified, respect both - expect_listequal(normalize_unhighlighted_aes(list(colour = "blue", fill = "red")), + expect_listequal(normalize_unhighlighted_params(list(colour = "blue", fill = "red")), list(colour = "blue", fill = "red")) # other parameters are left as is - expect_listequal(normalize_unhighlighted_aes(list(fill = "red", size = 0.2)), + expect_listequal(normalize_unhighlighted_params(list(fill = "red", size = 0.2)), list(colour = "red", fill = "red", size = 0.2)) # color is an alias of colour - expect_listequal(normalize_unhighlighted_aes(list(color = "red")), + expect_listequal(normalize_unhighlighted_params(list(color = "red")), list(colour = "red", fill = "red")) # if both colour and color are specified, use colour. - expect_listequal(normalize_unhighlighted_aes(list(colour = "blue", color = "red")), + expect_listequal(normalize_unhighlighted_params(list(colour = "blue", color = "red")), list(colour = "blue", fill = "blue")) # if both fill and colour are missing, raise error - expect_listequal(normalize_unhighlighted_aes(list()), + expect_listequal(normalize_unhighlighted_params(list()), list(colour = ggplot2::alpha("grey", 0.7), fill = ggplot2::alpha("grey", 0.7))) }) From 396d36d2b306fa08ec4575d8445e62b927b55708 Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 18:24:24 +0900 Subject: [PATCH 6/8] Add a NEWS bullet --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 427b6f2..06c9bfa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # gghighlight 0.1.0.9000 +* `gghighlight()` gets a new argument `unhighlighted_params`, which accepts a + list of parameters for the unhighlighted layer (e.g. `colour`, `fill`, `shape`, + and `size`). Accordingly, `unhighlighted_colour` is deprecated (#76). + # gghighlight 0.1.0 * Add `gghighlight()`, which replaces the current `gghighlight_line()` and `gghighlight_point()`; these functions are now deprecated. From 907b70667b914aa5faf606b2af050905f54238dc Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 20:37:11 +0900 Subject: [PATCH 7/8] Change the default value --- R/gghighlight.R | 52 +++++++++++++++++-------------- tests/testthat/test-gghighlight.R | 39 ++++++++++++++--------- tests/testthat/test-internals.R | 14 ++------- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/R/gghighlight.R b/R/gghighlight.R index 41ada89..b81757a 100644 --- a/R/gghighlight.R +++ b/R/gghighlight.R @@ -44,7 +44,7 @@ gghighlight <- function(..., n = NULL, max_highlight = 5L, - unhighlighted_params = list(colour = ggplot2::alpha("grey", 0.7)), + unhighlighted_params = list(), use_group_by = NULL, use_direct_label = NULL, label_key = NULL, @@ -227,16 +227,17 @@ calculate_group_info <- function(data, mapping) { } bleach_layer <- function(layer, group_info, unhighlighted_params) { + # `colour` and `fill` are special in that they needs to be specified even when + # it is not included in unhighlighted_params. But, if the default_aes is NA, + # respect it (e.g. geom_bar()'s default colour is NA). + # Note that this depends on the mapping, so this needs to be done before modifying the mapping. + unhighlighted_params$colour <- unhighlighted_params$colour %||% get_default_aes_param("colour", layer$geom, layer$mapping) + unhighlighted_params$fill <- unhighlighted_params$fill %||% get_default_aes_param("fill", layer$geom, layer$mapping) # c.f. https://github.com/tidyverse/ggplot2/blob/e9d4e5dd599b9f058cbe9230a6517f85f3587567/R/layer.r#L107-L108 aes_params_bleached <- unhighlighted_params[names(unhighlighted_params) %in% layer$geom$aesthetics()] geom_params_bleached <- unhighlighted_params[names(unhighlighted_params) %in% layer$geom$parameters(TRUE)] - # Use the colour and fill specified in unhighlighted_params when it is included in - # the mappping. But, if the default_aes is NA, respect it. - # (Note that this needs to be executed before modifying the layer$mapping) - aes_params_bleached <- fill_unhighlighted_params_with_na(aes_params_bleached, layer$geom, layer$mapping) - layer$aes_params <- utils::modifyList(layer$aes_params, aes_params_bleached) layer$geom_params <- utils::modifyList(layer$geom_params, geom_params_bleached) @@ -264,17 +265,30 @@ bleach_layer <- function(layer, group_info, unhighlighted_params) { layer } -fill_unhighlighted_params_with_na <- function(unhighlighted_params, geom, mapping) { - aes_name <- names(unhighlighted_params) +default_unhighlighted_params <- list( + colour = ggplot2::alpha("grey", 0.7), + fill = ggplot2::alpha("grey", 0.7) +) + +get_default_aes_param <- function(aes_param_name, geom, mapping) { + # no default is available + if (!aes_param_name %in% names(default_unhighlighted_params)) { + return(NULL) + } - # if aes_name is not specified in the mapping and the default_aes is NA, use NA. - is_default_na <- !aes_name %in% names(mapping) & - aes_name %in% names(geom$default_aes) & - is.na(geom$default_aes[aes_name]) + # if it is specified in mapping, it needs to be overriden + if (aes_param_name %in% names(mapping)) { + return(default_unhighlighted_params[[aes_param_name]]) + } - unhighlighted_params[is_default_na] <- NA + # if the geom has default value and is NA, use NA + if (aes_param_name %in% names(geom$default_aes) && + is.na(geom$default_aes[[aes_param_name]])) { + return(NA) + } - unhighlighted_params + # otherwise, use the default grey + default_unhighlighted_params[[aes_param_name]] } sieve_layer <- function(layer, group_info, predicates, @@ -389,15 +403,5 @@ normalize_unhighlighted_params <- function(aes_params) { aes_params$color <- NULL } - # if both fill and colour are missing, use the default value - if (is.null(aes_params$colour) && is.null(aes_params$fill)) { - aes_params$colour <- ggplot2::alpha("grey", 0.7) - aes_params$fill <- ggplot2::alpha("grey", 0.7) - return(aes_params) - } - - # if fill or colour is missing, use the other for it - aes_params$colour <- aes_params$colour %||% aes_params$fill - aes_params$fill <- aes_params$fill %||% aes_params$colour aes_params } diff --git a/tests/testthat/test-gghighlight.R b/tests/testthat/test-gghighlight.R index c4076de..0677e96 100644 --- a/tests/testthat/test-gghighlight.R +++ b/tests/testthat/test-gghighlight.R @@ -2,7 +2,6 @@ context("test-gghighlight.R") library(ggplot2) grey07 <- ggplot2::alpha("grey", 0.7) -grey09 <- ggplot2::alpha("grey", 0.9) d <- tibble::tribble( ~x, ~y, ~type, ~value, @@ -21,7 +20,7 @@ g_info <- list(data = d_, id = ids, key = aes(colour = type)) expect_equal_layer <- function(x, y) { x$mapping <- x$mapping[sort(names(x$mapping))] - y$mapping <- x$mapping[sort(names(y$mapping))] + y$mapping <- y$mapping[sort(names(y$mapping))] expect_equal(x, y) } @@ -88,40 +87,50 @@ aes_bleached <- aes_string(x = paste0(prefix, 1), group = paste0(prefix, "group")) test_that("bleach_layer() works", { - aes_grey07 <- normalize_unhighlighted_params(list(colour = grey07)) - # If colour is specified, colour is used as the group key. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, list()), geom_line(aes_bleached, d_bleached, colour = grey07)) # If colour is specified but group_key is NULL, the result is the same data. - expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, aes_grey07), + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), NULL, list()), geom_line(aes(colour = NULL, fill = NULL), d, colour = grey07)) # If the geom accepts fill, it is sets to grey even when it is not included in the mapping. - expect_equal_layer(bleach_layer(geom_col(aes(colour = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_col(aes(colour = type), d), g_info, list()), geom_col(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If the default of colour of the geom is NA and mapping doesn't specify it, params will be NA. - expect_equal_layer(bleach_layer(geom_col(aes(fill = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_col(aes(fill = type), d), g_info, list()), geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) # If colour and fill is specified at the same time, fill is used as the group key. - expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, list()), geom_col(aes_bleached, d_bleached, colour = grey07, fill = grey07)) # If mapping doesn't have colour or fill, group or x aes can be used as group key. # c.f. https://github.com/yutannihilation/gghighlight/pull/17#issuecomment-390486101. - expect_equal_layer(bleach_layer(geom_col(aes(group = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_col(aes(group = type), d), g_info, list()), geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) - expect_equal_layer(bleach_layer(geom_col(aes(x = type), d), g_info, aes_grey07), + expect_equal_layer(bleach_layer(geom_col(aes(x = type), d), g_info, list()), geom_col(aes_bleached, d_bleached, colour = NA, fill = grey07)) # unhighlighted_params can be more detailed - aes_grey07_and_more <- normalize_unhighlighted_params(list(colour = grey09, fill = grey07, width = 0.5)) - - expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, aes_grey07_and_more), - geom_col(aes_bleached, d_bleached, colour = grey09, fill = grey07, width = 0.5)) + expect_equal_layer(bleach_layer(geom_line(aes(colour = type), d), g_info, + list(colour = "blue", size = 3)), + geom_line(aes_bleached, d_bleached, colour = "blue", size = 3)) + + expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, + list(colour = "blue", width = 0.5)), + geom_col(aes_bleached, d_bleached, colour = "blue", fill = grey07, width = 0.5)) + + expect_equal_layer(bleach_layer(geom_col(aes(fill = type), d), g_info, + list(fill = "blue", width = 0.5)), + # TODO: the order of fill and colour matters here... + geom_col(aes_bleached, d_bleached, fill = "blue", colour = NA, width = 0.5)) + + expect_equal_layer(bleach_layer(geom_col(aes(colour = type, fill = type), d), g_info, + list(colour = ggplot2::alpha("grey", 0.9), fill = grey07, width = 0.5)), + geom_col(aes_bleached, d_bleached, colour = ggplot2::alpha("grey", 0.9), fill = grey07, width = 0.5)) }) test_that("sieve_layer() works with simple cases", { diff --git a/tests/testthat/test-internals.R b/tests/testthat/test-internals.R index 27b9511..bb67e91 100644 --- a/tests/testthat/test-internals.R +++ b/tests/testthat/test-internals.R @@ -21,24 +21,16 @@ test_that("normalize_unhighlighted_params() works", { expect_equal(!!x[sort(names(x))], !!y[sort(names(y))]) } - # if fill or colour is missing, use the other for it - expect_listequal(normalize_unhighlighted_params(list(colour = "red")), - list(colour = "red", fill = "red")) - expect_listequal(normalize_unhighlighted_params(list(fill = "red")), - list(colour = "red", fill = "red")) # if fill and colour is specified, respect both expect_listequal(normalize_unhighlighted_params(list(colour = "blue", fill = "red")), list(colour = "blue", fill = "red")) # other parameters are left as is expect_listequal(normalize_unhighlighted_params(list(fill = "red", size = 0.2)), - list(colour = "red", fill = "red", size = 0.2)) + list(fill = "red", size = 0.2)) # color is an alias of colour expect_listequal(normalize_unhighlighted_params(list(color = "red")), - list(colour = "red", fill = "red")) + list(colour = "red")) # if both colour and color are specified, use colour. expect_listequal(normalize_unhighlighted_params(list(colour = "blue", color = "red")), - list(colour = "blue", fill = "blue")) - # if both fill and colour are missing, raise error - expect_listequal(normalize_unhighlighted_params(list()), - list(colour = ggplot2::alpha("grey", 0.7), fill = ggplot2::alpha("grey", 0.7))) + list(colour = "blue")) }) From 5e0289d10ed5028f9e2569c3da0f53f64d58a157 Mon Sep 17 00:00:00 2001 From: Hiroaki Yutani Date: Fri, 28 Dec 2018 20:42:48 +0900 Subject: [PATCH 8/8] Regenerate doc --- man/gghighlight.Rd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/gghighlight.Rd b/man/gghighlight.Rd index dc8fdef..f8917c3 100644 --- a/man/gghighlight.Rd +++ b/man/gghighlight.Rd @@ -5,9 +5,9 @@ \title{Highlight Data With Predicate} \usage{ gghighlight(..., n = NULL, max_highlight = 5L, - unhighlighted_params = list(colour = ggplot2::alpha("grey", 0.7)), - use_group_by = NULL, use_direct_label = NULL, label_key = NULL, - label_params = list(fill = "white"), unhighlighted_colour = NULL) + unhighlighted_params = list(), use_group_by = NULL, + use_direct_label = NULL, label_key = NULL, label_params = list(fill + = "white"), unhighlighted_colour = NULL) } \arguments{ \item{...}{Expressions to filter data, which is passed to \code{\link[dplyr:filter]{dplyr::filter()}}.}