Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include literal curly brackets in tbl_summary() #2123

Closed
ddsjoberg opened this issue Jan 16, 2025 · 8 comments · Fixed by #2133
Closed

Include literal curly brackets in tbl_summary() #2123

ddsjoberg opened this issue Jan 16, 2025 · 8 comments · Fixed by #2133
Milestone

Comments

@ddsjoberg
Copy link
Owner

ddsjoberg commented Jan 16, 2025

Reported here: https://stackoverflow.com/questions/79362375

library(magrittr)

gtsummary::tbl_summary(mtcars, statistic = all_continuous() ~ "\\makecell{{{mean}}}")
#> Error in `gtsummary::tbl_summary()`:
#> ! Error processing `statistic` argument.
#> ! Caused by error in `all_continuous()`: ! could not find function
#>   "all_continuous"
#> ℹ Select among columns "mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs",
#>   "am", "gear", and "carb"

.extract_glue_elements <- function(x) {
  regmatches(x, gregexpr("\\{([^\\}]*)\\}", x)) |>
    unlist() %>%
    {substr(., 2, nchar(.) - 1)} # styler: off
}

.extract_glue_elements("\\makecell{mean}")     # should return `c('mean')`
#> [1] "mean"
.extract_glue_elements("\\makecell{{mean}}")   # should return `character(0L)`
#> [1] "{mean"
.extract_glue_elements("\\makecell{{{mean}}}") # should return `c('mean')`
#> [1] "{{mean"

# these will eventually be processed with glue()
glue::glue("{letters[1]}")
#> a
glue::glue("{{letters[1]}}")
#> {letters[1]}
glue::glue("{{{letters[1]}}}")
#> {a}

Created on 2025-01-16 with reprex v2.1.1

@raffaem
Copy link

raffaem commented Jan 16, 2025

Can't we just remove {{ and }} before extract_glue_elements?

@ddsjoberg
Copy link
Owner Author

That's a good point @raffaem, thanks !

Perhaps something like this would work, where we iteratively remove pairs of double curlies...

library(magrittr)

# attaching two internal functions form gtsummary
str_detect <- gtsummary:::str_detect
str_remove <- gtsummary:::str_remove

.extract_glue_elements <- function(x) {
  # remove PAIRS fo double curly brackets 
  while (str_detect(x, pattern = "{{", fixed = TRUE) && str_detect(x, pattern = "}}", fixed = TRUE)) {
    x <- str_remove(x, "{{", fixed = TRUE) |> str_remove(x, "}}", fixed = TRUE)
  }
  
  regmatches(x, gregexpr("\\{([^\\}]*)\\}", x)) |>
    unlist() %>%
    {substr(., 2, nchar(.) - 1)} # styler: off
}

.extract_glue_elements("\\makecell{mean}") # should return `c('mean')`
#> [1] "mean"
.extract_glue_elements("\\makecell{{mean}}") # should return `character(0L)`
#> character(0)
.extract_glue_elements("\\makecell{{{mean}}}") # should return `c('mean')`
#> [1] "mean"
.extract_glue_elements("{{{mean}}}}") # should return `c('mean')` (unbalanced curlies)
#> [1] "mean"

Created on 2025-01-16 with reprex v2.1.1

@ddsjoberg
Copy link
Owner Author

Welp, it almost works with the code below....if we remove pairs of double curly brackets, it'll work in a well-defined space, but if curly brackets appear in another space we still see the parsing error.... 🤔🤔🤔

.extract_glue_elements <- function(x) {
  # remove PAIRS of double curly brackets
  while (isTRUE(any(str_detect(x, pattern = "{{", fixed = TRUE) & str_detect(x, pattern = "}}", fixed = TRUE)))) {
    idx <- str_detect(x, pattern = "{{", fixed = TRUE) & str_detect(x, pattern = "}}", fixed = TRUE)
    x[idx] <- str_remove(x[idx], "{{", fixed = TRUE) |> str_remove("}}", fixed = TRUE)
  }

  regmatches(x, gregexpr("\\{([^\\}]*)\\}", x)) |>
    unlist() %>%
    {substr(., 2, nchar(.) - 1)} # styler: off
}
devtools::load_all(path = "/Users/sjobergd/Documents/GitHub/gtsummary")
#> ℹ Loading gtsummary

tbl_summary(mtcars["mpg"], statistic = all_continuous() ~ "\\makecell{{{mean}}}") |> as.data.frame()
#>   **Characteristic**       **N = 32**
#> 1                mpg \\makecell{20.1}
tbl_summary(mtcars["mpg"], statistic = all_continuous() ~ "\\mak{{ecell{{{mean}}}") |> as.data.frame()
#> Error in `tbl_summary()`:
#> ! Problem with the `statistic` argument.
#> Error converting string "{{mean" to a function.
#> ℹ Is the name spelled correctly and available?

Created on 2025-01-16 with reprex v2.1.1

@ddsjoberg
Copy link
Owner Author

Probably should investigate the glue code and steal what they have there....

@raffaem
Copy link

raffaem commented Jan 17, 2025

I don't understand what "well defined space" and "another space" mean.
I don't think the case of unbalanced curlies is legal.
Why we are using those functions instead of stringr?

@raffaem
Copy link

raffaem commented Jan 17, 2025

.extract_glue_elements <- function(x) {
  x <- stringr::str_replace_all(x, "(\\{\\{)|(\\}\\})", "")
  regmatches(x, gregexpr("\\{([^\\}]*)\\}", x)) |>
    unlist() %>%
    {
      substr(., 2, nchar(.) - 1)
    }
}
> tbl_summary(mtcars["mpg"], statistic = all_continuous() ~ "\\makecell{{{mean}}}") |> as.data.frame()
  **Characteristic**       **N = 32**
1                mpg \\makecell{20.1}
> tbl_summary(mtcars["mpg"], statistic = all_continuous() ~ "\\mak{{ecell{{{mean}}}") |> as.data.frame()
  **Characteristic**        **N = 32**
1                mpg \\mak{ecell{20.1}

@ddsjoberg ddsjoberg added this to the v2.1.0 milestone Jan 27, 2025
@ddsjoberg
Copy link
Owner Author

Unfortunately, that doesn't quite solve the problem. it's tricky to mimic glue::glue()

library(magrittr)

.extract_glue_elements <- function(x) {
  x <- stringr::str_replace_all(x, "(\\{\\{)|(\\}\\})", "")
  regmatches(x, gregexpr("\\{([^\\}]*)\\}", x)) |>
    unlist() %>%
    substr(start = 2, stop = nchar(.) - 1)
}
.extract_glue_elements("{{{{{mean}}}}}}")
#> character(0)
glue::glue("{{{{{letters[1]}}}}}}")
#> {{a}}}

Created on 2025-01-29 with reprex v2.1.1

@ddsjoberg
Copy link
Owner Author

@raffaem I think I have something working here: #2133

If you have a moment, can you please try to break it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants