tidyeval and plot functions

Two questions

  1. Trying to figure out how to get the y_position of the p value bars in the right place in an automated way, by calculating the max of {{contvar}}. Hoping to use max* 1.1 or max *1.2 to put these in staggered locations. Clearly doing something wrong. I want to get out a constant for max.

  2. I would also like to use {glue} to glue in titles and axis labels that automatically include the correct catvar and contvar. This is not working in my few futile attempts. Things like `x = glue("Measurement of {{contvar}}"), which gives me "Measurement of {contvar}" as an x label.

Reprex below

library(tidyverse)
library(palmerpenguins)
library(ggsignif)

plot_cats <- function(data, catvar, contvar){
  data %>%
    mutate(max := max({{contvar}})) |> 
    ggplot() +
        aes(x = {{contvar}}, y = factor({{catvar}}), 
        fill=factor({{catvar}})) +
    geom_jitter(width = 0.6) +
    geom_boxplot() +
    geom_signif(comparisons = list(c(1,2))) +
    geom_signif(comparisons = list(c(1,3)), 
                y_position = 1.1 * max) +
    geom_signif(comparisons = list(c(2,3)), 
                y_position = 1.2 * max) +
    theme_bw() +
    theme(legend.position = "none",
          panel.grid.major.x  = element_blank()) +
    labs(y = "",
         x = glue("Measurement of {{contvar}}"))
}

plot_cats(penguins, catvar = island, contvar = bill_length_mm)
#> Error in 1.1 * max: non-numeric argument to binary operator

Created on 2023-09-01 with reprex v2.0.2

library(tidyverse)
library(palmerpenguins)
library(ggsignif)
library(glue)

plot_cats <- function(data, catvar, contvar){
  mv <- transmute(data,
                  max := max({{contvar}},na.rm=TRUE)) |> 
    pull(max)
  
  data |> 
    ggplot() +
    aes(x = {{contvar}}, y = factor({{catvar}}), 
        fill=factor({{catvar}})) +
    geom_jitter(width = 0.6) +
    geom_boxplot() +
    geom_signif(comparisons = list(c(1,2))) +
    geom_signif(comparisons = list(c(1,3)), 
                y_position = 1.1 * mv) +
    geom_signif(comparisons = list(c(2,3)), 
                y_position = 1.2 * mv) +
    theme_bw() +
    theme(legend.position = "none",
          panel.grid.major.x  = element_blank()) +
    labs(y = "",
         x = glue("Measurement of {ensym(contvar)}"))
}

plot_cats(penguins, catvar = island, contvar = bill_length_mm)

Puzzled by contvar vs catvar in map2 (seem switched),
and by why the all combinations version does not work at all.

library(tidyverse)
library(palmerpenguins)
library(ggsignif)
library(glue)

# adaptive function will adjust p value bar height , title, and x axis label
plot_cats <- function(data, catvar, contvar){
  mv <- transmute(data,
      max := max({{contvar}},na.rm=TRUE)) |> 
    pull(max)
  
  data |> 
    ggplot() +
    aes(x = {{contvar}}, y = factor({{catvar}}), 
        fill=factor({{catvar}})) +
    geom_boxplot() +
    geom_jitter(width = 0.6) +
    geom_signif(comparisons = list(c(1,2))) +
    geom_signif(comparisons = list(c(1,3)), 
                y_position = 1.1 * mv) +
    geom_signif(comparisons = list(c(2,3)), 
                y_position = 1.2 * mv) +
    theme_bw() +
    theme(legend.position = "none",
          panel.grid.major.x  = element_blank()) +
    labs(y = "",
         x = glue("Measurement of {ensym(contvar)}"),
         title = glue("Comparison of {ensym(contvar)} \nAcross {ensym(catvar)} categories" ))
}

plot_cats(penguins, catvar = island, contvar = bill_length_mm)
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).



# Now make vector lists of catvars and contvars
catvars <- c('island', 'species', 'sex')

contvars <- c('bill_length_mm', 'body_mass_g', 'flipper_length_mm')

# Now plot the 3 pairs - works find with syms
# though it seems like contvars should be .x
# and catvars should be .y - but this version works

map2(.x = syms(catvars),
     .y = syms(contvars),
     .f = plot_cats, 
    data = penguins)
#> [[1]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).

#> 
#> [[2]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).

#> 
#> [[3]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).


# note this does the 3 pairs of catvars with contvars.
# to do all (9) combinations, let's set that up
# with an anaysis_list dataframe of all combos

analysis_list <- crossing(catvars, contvars)

# now for all possible (9) combinations
# This does NOT work
map2(.x = syms(analysis_list$catvars), 
     .y = syms(analysis_list$contvars), 
     .f = plot, 
     data = penguins) # all combos of x, y
#> Error in `map2()`:
#> ℹ In index: 1.
#> Caused by error in `as.double()`:
#> ! cannot coerce type 'symbol' to vector of type 'double'
#> Backtrace:
#>      ▆
#>   1. ├─purrr::map2(...)
#>   2. │ └─purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
#>   3. │   ├─purrr:::with_indexed_errors(...)
#>   4. │   │ └─base::withCallingHandlers(...)
#>   5. │   ├─purrr:::call_with_cleanup(...)
#>   6. │   ├─base (local) .f(.x[[i]], .y[[i]], ...)
#>   7. │   └─graphics::plot.default(.x[[i]], .y[[i]], ...)
#>   8. │     └─grDevices::xy.coords(x, y, xlabel, ylabel, log)
#>   9. └─base::.handleSimpleError(...)
#>  10.   └─purrr (local) h(simpleError(msg, call))
#>  11.     └─cli::cli_abort(...)
#>  12.       └─rlang::abort(...)

Created on 2023-09-06 with reprex v2.0.2

I am a little bit surprised that this works, as pull(max) results in a long vector (the length of the data frame).
I had assumed that you would need a vector of length 1, but y_position = 1.2 * mv seems just fine with it.

To help me understand this better, why is this OK, and there is not an error/warning about y_position being a long vector when it only needs to be length 1?

Also puzzling: When I run this as pairs of values through map2, it works fine

library(tidyverse)
library(palmerpenguins)
library(ggsignif)
library(glue)

plot_cats <- function(data, catvar, contvar){
  mv <- transmute(data,
    max := max({{contvar}},na.rm=TRUE)) |> 
    pull(max)
  
  data |> 
    ggplot() +
    aes(x = {{contvar}}, y = factor({{catvar}}), 
        fill=factor({{catvar}})) +
    geom_boxplot() +
    geom_jitter(width = 0.6) +
    geom_signif(comparisons = list(c(1,2))) +
    geom_signif(comparisons = list(c(1,3)), 
                y_position = 1.1 * mv) +
    geom_signif(comparisons = list(c(2,3)), 
                y_position = 1.2 * mv) +
    theme_bw() +
    theme(legend.position = "none",
          panel.grid.major.x  = element_blank()) +
    labs(y = "",
         x = glue("Measurement of {ensym(contvar)}"),
         title = glue("Comparison of {ensym(contvar)} \nAcross {ensym(catvar)} categories" ))
}
# Make vector lists of catvars and contvars
catvars <- c('island', 'species', 'sex')

contvars <- c('bill_length_mm', 'body_mass_g', 'flipper_length_mm')

# Now plot the 3 pairs
map2(.x = syms(catvars),
     .y = syms(contvars),
     .f = plot_cats, 
    data = penguins)
#> [[1]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).

#> 
#> [[2]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).

#> 
#> [[3]]
#> Warning: Removed 2 rows containing non-finite values (`stat_boxplot()`).
#> Warning: Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Removed 2 rows containing non-finite values (`stat_signif()`).
#> Warning: Removed 2 rows containing missing values (`geom_point()`).

Created on 2023-09-02 with reprex v2.0.2

But when I try to do all possible combinations with crossing, somehow it goes haywire. It looks quite similar, but there must be something subtle going wrong. Any help appreciated.

library(tidyverse)
library(palmerpenguins)
library(ggsignif)
library(glue)

plot_cats <- function(data, catvar, contvar){
  mv <- transmute(data,
                  max := max({{contvar}},na.rm=TRUE)) |> 
    pull(max)
  
  data |> 
    ggplot() +
    aes(x = {{contvar}}, y = factor({{catvar}}), 
        fill=factor({{catvar}})) +
    geom_boxplot() +
    geom_jitter(width = 0.6) +
    geom_signif(comparisons = list(c(1,2))) +
    geom_signif(comparisons = list(c(1,3)), 
                y_position = 1.1 * mv) +
    geom_signif(comparisons = list(c(2,3)), 
                y_position = 1.2 * mv) +
    theme_bw() +
    theme(legend.position = "none",
          panel.grid.major.x  = element_blank()) +
    labs(y = "",
         x = glue("Measurement of {ensym(contvar)}"),
         title = glue("Comparison of {ensym(contvar)} \nAcross {ensym(catvar)} categories" ))
}

catvars <- c('island', 'species', 'sex')

contvars <- c('bill_length_mm', 'body_mass_g', 'flipper_length_mm')
analysis_list <- crossing(catvars, contvars)

# now for all possible (9) combinations
map2(.x = syms(analysis_list$catvars), 
     .y = syms(analysis_list$contvars), 
     .f = plot, 
     data = penguins) # all combos of x, y
#> Error in `map2()`:
#> ℹ In index: 1.
#> Caused by error in `as.double()`:
#> ! cannot coerce type 'symbol' to vector of type 'double'
#> Backtrace:
#>      ▆
#>   1. ├─purrr::map2(...)
#>   2. │ └─purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
#>   3. │   ├─purrr:::with_indexed_errors(...)
#>   4. │   │ └─base::withCallingHandlers(...)
#>   5. │   ├─purrr:::call_with_cleanup(...)
#>   6. │   ├─base (local) .f(.x[[i]], .y[[i]], ...)
#>   7. │   └─graphics::plot.default(.x[[i]], .y[[i]], ...)
#>   8. │     └─grDevices::xy.coords(x, y, xlabel, ylabel, log)
#>   9. └─base::.handleSimpleError(...)
#>  10.   └─purrr (local) h(simpleError(msg, call))
#>  11.     └─cli::cli_abort(...)
#>  12.       └─rlang::abort(...)

Created on 2023-09-02 with reprex v2.0.2

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.