From 99a1222ce52ba5594c01ffe3bd6b5e776d6ae680 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Sat, 1 Mar 2025 18:01:22 +0100 Subject: [PATCH 1/5] fix linetype scale --- scales-other.qmd | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/scales-other.qmd b/scales-other.qmd index 68a198e9..cf687c89 100644 --- a/scales-other.qmd +++ b/scales-other.qmd @@ -245,26 +245,25 @@ base <- ggplot(df, aes(linetype = value)) + base ``` -You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. This allows you to specify your own line types using `scale_linetype_manual()`, or alternatively, by passing a custom function to the `palette` argument: +You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). +In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. +This allows you to specify your own line types using `scale_linetype_manual()`: ```{r} #| eval: false -linetypes <- function(n) { - types <- c( - "55", - "75", - "95", - "1115", - "111115", - "11111115", - "5158", - "9198", - "c1c8" - ) - return(types[seq_len(n)]) -} +types <- c( + "55", + "75", + "95", + "1115", + "111115", + "11111115", + "5158", + "9198", + "c1c8" +) -base + scale_linetype(palette = linetypes) +base + scale_linetype_manual(values = linetypes) ``` Note that the last four lines are blank, because the `linetypes()` function defined above returns `NA` when the number of categories exceeds 9. The `scale_linetype()` function contains a `na.value` argument used to specify what kind of line is plotted for these values. By default this produces a blank line, but you can override this by setting `na.value = "dotted"`: From ea7967e12aac6939224603477f357098660bf640 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Sat, 1 Mar 2025 18:02:31 +0100 Subject: [PATCH 2/5] fix outdated alternative build functions --- internals_ggbuild.R | 8 ++--- internals_gggtable.R | 72 ++------------------------------------------ 2 files changed, 6 insertions(+), 74 deletions(-) diff --git a/internals_ggbuild.R b/internals_ggbuild.R index 0c77e29d..75e0c948 100644 --- a/internals_ggbuild.R +++ b/internals_ggbuild.R @@ -50,7 +50,7 @@ ggbuild <- function(plot) { # Transform all scales - data <- lapply(data, ggplot2:::scales_transform_df, scales = scales) # ****** + data <- lapply(data, scales$transform_df) # ****** # Record the layer data after scale transformation applied all_steps$transformed <- data # ****** @@ -74,7 +74,7 @@ ggbuild <- function(plot) { all_steps$poststat <- data # ****** # Make sure missing (but required) aesthetics are added - ggplot2:::scales_add_missing(plot, c("x", "y"), plot$plot_env) # ****** + scales$add_missing(c("x", "y"), plot$plot_env) # ****** # Reparameterise geoms from (e.g.) y and width to ymin and ymax data <- by_layer(function(l, d) l$compute_geom_1(d)) @@ -96,8 +96,8 @@ ggbuild <- function(plot) { # Train and map non-position scales npscales <- scales$non_position_scales() if (npscales$n() > 0) { - lapply(data, ggplot2:::scales_train_df, scales = npscales) # ****** - data <- lapply(data, ggplot2:::scales_map_df, scales = npscales) # ****** + lapply(data, npscales$train_df) # ****** + data <- lapply(data, npscales$map_df) # ****** } # Fill in defaults etc. diff --git a/internals_gggtable.R b/internals_gggtable.R index 17d4a722..adf4ff0b 100644 --- a/internals_gggtable.R +++ b/internals_gggtable.R @@ -19,7 +19,6 @@ gggtable <- function(data) { theme <- ggplot2:::plot_theme(plot) # ****** geom_grobs <- Map(function(l, d) l$draw_geom(d, layout), plot$layers, data) - layout$setup_panel_guides(plot$guides, plot$layers, plot$mapping) plot_table <- layout$render(geom_grobs, data, theme, plot$labels) # Record the state after the panel layouts have done their job (I think!) @@ -32,75 +31,8 @@ gggtable <- function(data) { position <- "manual" } - legend_box <- if (position != "none") { - ggplot2:::build_guides(plot$scales, plot$layers, plot$mapping, position, theme, plot$guides, plot$labels) # ****** - } else { - zeroGrob() - } - - if (ggplot2:::is.zero(legend_box)) { # ****** - position <- "none" - } else { - # these are a bad hack, since it modifies the contents of viewpoint directly... - legend_width <- gtable:::gtable_width(legend_box) # ****** - legend_height <- gtable:::gtable_height(legend_box) # ****** - - # Set the justification of the legend box - # First value is xjust, second value is yjust - just <- grid::valid.just(theme$legend.justification) # ****** - xjust <- just[1] - yjust <- just[2] - - if (position == "manual") { - xpos <- theme$legend.position[1] - ypos <- theme$legend.position[2] - - # x and y are specified via theme$legend.position (i.e., coords) - legend_box <- grid::editGrob(legend_box, # ****** - vp = grid::viewport(x = xpos, y = ypos, just = c(xjust, yjust), # ****** - height = legend_height, width = legend_width)) - } else { - # x and y are adjusted using justification of legend box (i.e., theme$legend.justification) - legend_box <- grid::editGrob(legend_box, # ****** - vp = grid::viewport(x = xjust, y = yjust, just = c(xjust, yjust))) # ****** - legend_box <- gtable:::gtable_add_rows(legend_box, unit(yjust, 'null')) # ****** - legend_box <- gtable:::gtable_add_rows(legend_box, unit(1 - yjust, 'null'), 0) # ****** - legend_box <- gtable:::gtable_add_cols(legend_box, unit(xjust, 'null'), 0) # ****** - legend_box <- gtable:::gtable_add_cols(legend_box, unit(1 - xjust, 'null')) # ****** - } - } - - panel_dim <- find_panel(plot_table) - # for align-to-device, use this: - # panel_dim <- summarise(plot_table$layout, t = min(t), r = max(r), b = max(b), l = min(l)) - - theme$legend.box.spacing <- theme$legend.box.spacing %||% unit(0.2, 'cm') - if (position == "left") { - plot_table <- gtable::gtable_add_cols(plot_table, theme$legend.box.spacing, pos = 0) # ****** - plot_table <- gtable::gtable_add_cols(plot_table, legend_width, pos = 0) # ****** - plot_table <- gtable::gtable_add_grob(plot_table, legend_box, clip = "off", # ****** - t = panel_dim$t, b = panel_dim$b, l = 1, r = 1, name = "guide-box") - } else if (position == "right") { - plot_table <- gtable::gtable_add_cols(plot_table, theme$legend.box.spacing, pos = -1) # ****** - plot_table <- gtable::gtable_add_cols(plot_table, legend_width, pos = -1) # ****** - plot_table <- gtable::gtable_add_grob(plot_table, legend_box, clip = "off", # ****** - t = panel_dim$t, b = panel_dim$b, l = -1, r = -1, name = "guide-box") - } else if (position == "bottom") { - plot_table <- gtable::gtable_add_rows(plot_table, theme$legend.box.spacing, pos = -1) # ****** - plot_table <- gtable::gtable_add_rows(plot_table, legend_height, pos = -1) # ****** - plot_table <- gtable::gtable_add_grob(plot_table, legend_box, clip = "off", # ****** - t = -1, b = -1, l = panel_dim$l, r = panel_dim$r, name = "guide-box") - } else if (position == "top") { - plot_table <- gtable::gtable_add_rows(plot_table, theme$legend.box.spacing, pos = 0) # ****** - plot_table <- gtable::gtable_add_rows(plot_table, legend_height, pos = 0) # ****** - plot_table <- gtable::gtable_add_grob(plot_table, legend_box, clip = "off", # ****** - t = 1, b = 1, l = panel_dim$l, r = panel_dim$r, name = "guide-box") - } else if (position == "manual") { - # should guide box expand whole region or region without margin? - plot_table <- gtable::gtable_add_grob(plot_table, legend_box, # ****** - t = panel_dim$t, b = panel_dim$b, l = panel_dim$l, r = panel_dim$r, - clip = "off", name = "guide-box") - } + legend_box <- plot$guides$assemble(theme) + plot_table <- ggplot2:::table_add_legends(plot_table, legend_box, theme) # Record the state of the gtable after the legends have been added all_states$legend <- plot_table # ****** From 6821200f816244370577746bb882c593942cc361 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Sat, 1 Mar 2025 18:20:46 +0100 Subject: [PATCH 3/5] bump ggplot2 version --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index f832f9ae..4bce9300 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,7 @@ Imports: ggforce, gghighlight, ggnewscale, - ggplot2, + ggplot2 (>= 3.5.0), ggraph, ggrepel, ggtext, From 592534b6571a1e3ee8e0d850080e6511fd8566c1 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Sat, 1 Mar 2025 18:50:00 +0100 Subject: [PATCH 4/5] Revert "fix linetype scale" This reverts commit 99a1222ce52ba5594c01ffe3bd6b5e776d6ae680. --- scales-other.qmd | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/scales-other.qmd b/scales-other.qmd index cf687c89..68a198e9 100644 --- a/scales-other.qmd +++ b/scales-other.qmd @@ -245,25 +245,26 @@ base <- ggplot(df, aes(linetype = value)) + base ``` -You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). -In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. -This allows you to specify your own line types using `scale_linetype_manual()`: +You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. This allows you to specify your own line types using `scale_linetype_manual()`, or alternatively, by passing a custom function to the `palette` argument: ```{r} #| eval: false -types <- c( - "55", - "75", - "95", - "1115", - "111115", - "11111115", - "5158", - "9198", - "c1c8" -) +linetypes <- function(n) { + types <- c( + "55", + "75", + "95", + "1115", + "111115", + "11111115", + "5158", + "9198", + "c1c8" + ) + return(types[seq_len(n)]) +} -base + scale_linetype_manual(values = linetypes) +base + scale_linetype(palette = linetypes) ``` Note that the last four lines are blank, because the `linetypes()` function defined above returns `NA` when the number of categories exceeds 9. The `scale_linetype()` function contains a `na.value` argument used to specify what kind of line is plotted for these values. By default this produces a blank line, but you can override this by setting `na.value = "dotted"`: From cac6703b7e9a1bc70a088fc16ed5287a6ecb5364 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 3 Mar 2025 15:01:21 +0100 Subject: [PATCH 5/5] Use `discrete_scale()` instead of `scale_linetype()` --- scales-other.qmd | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scales-other.qmd b/scales-other.qmd index 68a198e9..3be05761 100644 --- a/scales-other.qmd +++ b/scales-other.qmd @@ -245,7 +245,9 @@ base <- ggplot(df, aes(linetype = value)) + base ``` -You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. This allows you to specify your own line types using `scale_linetype_manual()`, or alternatively, by passing a custom function to the `palette` argument: +You can control the line type by specifying a string with up to 8 hexadecimal values (i.e., from 0 to F). +In this specification, the first value is the length of the first line segment, the second value is the length of the first space between segments, and so on. +This allows you to specify your own line types using `scale_linetype_manual()`, or alternatively, by passing a custom function to the `palette` argument: ```{r} #| eval: false @@ -264,14 +266,16 @@ linetypes <- function(n) { return(types[seq_len(n)]) } -base + scale_linetype(palette = linetypes) +base + discrete_scale("linetype", palette = linetypes) ``` -Note that the last four lines are blank, because the `linetypes()` function defined above returns `NA` when the number of categories exceeds 9. The `scale_linetype()` function contains a `na.value` argument used to specify what kind of line is plotted for these values. By default this produces a blank line, but you can override this by setting `na.value = "dotted"`: +Note that the last four lines are blank, because the `linetypes()` function defined above returns `NA` when the number of categories exceeds 9. +The `discrete_scale()` function contains a `na.value` argument used to specify what kind of line is plotted for these values. +By default this produces a blank line, but you can override this by setting `na.value = "dotted"`: ```{r} #| eval: false -base + scale_linetype(palette = linetypes, na.value = "dotted") +base + discrete_scale("linetype", palette = linetypes) ``` Valid line types can be set using a human readable character string: `"blank"`, `"solid"`, `"dashed"`, `"dotted"`, `"dotdash"`, `"longdash"`, and `"twodash"` are all understood.