1

I have some code that calculates quantiles and saves it under a new variable. Now I am trying to modify the code so I can use it in a loop. Here is a sample dataset, the original code, and the output.

df <- data.frame(country = c("Algeria", "Egypt", "Ethiopia"), 
                 ward_1 = c(25, 75, 35),
                 ward_2 = c(30, 185, 60))

df %>%
  mutate(
    ward_1_quant = case_when(
      ward_1 >= quantile(df$ward_1, 2/3) ~"High",
      ward_1 >= quantile(df$ward_1, 1/3) ~"Med",
      TRUE~"Low"
    )
  )

df <- data.frame(country = c("Algeria", "Egypt", "Ethiopia"), 
                 ward_1 = c(25, 75, 35),
                 ward_2 = c(30, 185, 60),
                 ward_1_quant = c(Low, Med, High))

Now I want to use the value of a variable "ward_num" to specify the column. I turn that into a string called "ward_name" and try to use it in the mutate(). Here is where I got stuck:

ward_num <- 2
ward_name <- paste0("ward_",ward_num)
df %>%
  mutate(
    paste0(ward_name,"_quant") = case_when(
      ward_name >= quantile(df[ward_name], 2/3) ~"High",
      ward_name >= quantile(df[ward_name], 1/3) ~"Med",
      TRUE~"Low"
    )
  )

r returns the error:

Error: unexpected '=' in: " mutate( paste0(ward_name,"_quant") ="

I think the issue is that I want to use the string in ward_name but the code is using ward_name literally. Any suggestions?

2 Answers 2

3

We may use .data with [[. Also, the expression on the lhs of = is not permitted. Instead use := and evaluate (!!) the paste expression

library(dplyr)
df %>%
  mutate(
    !! paste0(ward_name,"_quant") := case_when(
      .data[[ward_name]] >= quantile(.data[[ward_name]], 2/3) ~"High",
      .data[[ward_name]] >= quantile(.data[[ward_name]], 1/3) ~"Med",
      TRUE~"Low"
    )
  )

-output

   country ward_1 ward_2 ward_2_quant
1  Algeria     25     30          Low
2    Egypt     75    185         High
3 Ethiopia     35     60          Med

Or another option is to pass this in across

df %>% 
  mutate(across(all_of(ward_name),
   ~ case_when(.x >= quantile(.x, 2/3) ~ "High", 
    .x >= quantile(.x, 1/3)~ "Med", TRUE ~ "Low"), 
      .names = "{.col}_quant"))
   country ward_1 ward_2 ward_2_quant
1  Algeria     25     30          Low
2    Egypt     75    185         High
3 Ethiopia     35     60          Med

Or another option is to use quantile with cut

df %>%
   mutate(across(all_of(ward_name),
   ~ cut(.x, breaks = c(-Inf, quantile(.x, probs = c(1/3, 2/3)), 
      Inf), labels = c("Low", "Med", "High")), .names = "{.col}_quant"))
     country ward_1 ward_2 ward_2_quant
1  Algeria     25     30          Low
2    Egypt     75    185         High
3 Ethiopia     35     60          Med
Sign up to request clarification or add additional context in comments.

Comments

1

Instead of messing around with across(), !! and its friends, I think it's better to use base R here.


ward_num <- 2
ward_name <- paste0("ward_",ward_num)
ward_name_quant <- paste0(ward_name,"_quant")
df[[ward_name_quant]] <- case_when(
                         df[[ward_name]] >= quantile(df[[ward_name]], 2/3) ~ "High",
                         df[[ward_name]] >= quantile(df[[ward_name]], 1/3) ~ "Med",
                         TRUE ~ "Low"
                       )
 

Also, you can use cut, or santoku::chop_quantiles() instead of the case_when call. (Side note: case_when is often a code smell.)

df[[ward_name_quant]] <- cut(df[[ward_name]], 
                             quantile(df[[ward_name]], c(0, 1/3, 2/3, 1)), 
                             c("Low", "Med", "High"), 
                             include.lowest = TRUE
                           )

# or

library(santoku)
df[[ward_name_quant]] <- chop_quantiles(df[[ward_name]], 
                                        c(1/3, 2/3), 
                                        c("Low", "Med", "High")
                                      )

1 Comment

I would suggest to use [[ instead of [ as this may lead to some buggy situations

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.