print variable name instead of value

Hi,

In the code below I have a list containing a single value. I want to check if each value is a double scaler. If not, then I want to print a name of that variable. Currently it is printing value to the variable and not the name of variable. I know the reason why it is so. But do not know how to solve this. Any help would be appriciated.

Thanks.

purrr::map(list(A = "xyz" , B = 1, C = 3 , D = 4,E = 5) ,
           function(x){
             x_enquo = rlang::enquo(x)
             x_name <- rlang::quo_name(x_enquo)
             if(!rlang::is_scalar_double(x)){
               stop(glue::glue("{x_name} must be a double of length 1."))
             }
           })
#> Error in .f(.x[[i]], ...): xyz must be a double of length 1.

Created on 2021-09-02 by the reprex package (v2.0.1)

Correction
Instead of a list, the input is a vector as shown

A = "XYZ"
B = 2
C= 3
D = 4
purrr::map(c(A,B,C,D) ,
           function(x){
             x_enquo = rlang::enquo(x)
             x_name <- rlang::quo_name(x_enquo)
             if(!rlang::is_scalar_double(x)){
               stop(glue::glue("{x_name} must be a double of length 1."))
             }
           })
#> Error in .f(.x[[i]], ...): XYZ must be a double of length 1.

Created on 2021-09-02 by the reprex package (v2.0.1)

Whether you pass the values in a list or a vector, if the values are named, then you can use the imap function and access both the value (represented by x below, just as in your function) and the name of the value (represented by y below). Both the vector version and list version work because the values are named.

vec = c(A="XYZ", B=2, C=3, D=4)
vec
#>     A     B     C     D 
#> "XYZ"   "2"   "3"   "4"

purrr::imap(vec,
            function(x,y){
              x_enquo = rlang::enquo(x)
              x_name <- rlang::quo_name(x_enquo)
              if(!rlang::is_scalar_double(x)) {
                stop(glue::glue("{y} must be a double of length 1."))
              }
            })
#> Error in .f(.x[[i]], .y[[i]], ...): A must be a double of length 1.

purrr::imap(list(A = "xyz" , B = 1, C = 3 , D = 4,E = 5) ,
            function(x,y){
              x_enquo = rlang::enquo(x)
              x_name <- rlang::quo_name(x_enquo)
              if(!rlang::is_scalar_double(x)) {
                stop(glue::glue("{y} must be a double of length 1."))
              }
            })
#> Error in .f(.x[[i]], .y[[i]], ...): A must be a double of length 1.

However, in the second example in your question, note that the vector doesn't have names, so there's no value name to report in the error message.

A = "XYZ"
B = 2
C= 3
D = 4

c(A,B,C,D)
#> [1] "XYZ" "2"   "3"   "4"

Also, just for future reference, you don't need to use function(x,y) { } when using the map functions. Instead, you can refer to the map variable as .x and the imap variables (the value and its name) as .x and .y. In the example below, note the tilde (~) before the ggplot function.

library(tidyverse)

purrr::imap(mtcars[ , 2:4], 
            ~ ggplot(mtcars, aes(.x, mpg)) + 
               geom_point() +
               labs(x=.y)) %>% 
  patchwork::wrap_plots()

If you have several separate lines of code, you can enclose them in braces. For your example, it would be:

purrr::imap(vec,
            ~ {
              x_enquo = rlang::enquo(.x)
              x_name <- rlang::quo_name(x_enquo)
              if(!rlang::is_scalar_double(.x)) {
                stop(glue::glue("{.y} must be a double of length 1."))
              }
            })
#> Error in .f(.x[[i]], .y[[i]], ...): A must be a double of length 1.
1 Like

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.