Home > Blockchain >  Perform a operation on the last column using mutate
Perform a operation on the last column using mutate

Time:08-19

Is there any way to reference the last column within mutate so that you can do an operation on it? For instance:

library(dplyr)
library(tidyr)
dat <- data.frame(
  col1 = c(1, 1, 1),
  col2 = c(0, 1, 0),
  col3 = c(2, 0, 2)
)

## what i was thinking:
dat %>%
  mutate(col1_bigger_than_col3 = col1 > last_col())
#> Error in `mutate()`:
#> ! Problem while computing `col1_bigger_than_col3 = col1 > last_col()`.
#> Caused by error:
#> ! `last_col()` must be used within a *selecting* function.
#> ℹ See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.

#> Backtrace:
#>      ▆
#>   1. ├─dat %>% mutate(col1_bigger_than_col3 = col1 > last_col())
#>   2. ├─dplyr::mutate(., col1_bigger_than_col3 = col1 > last_col())
#>   3. ├─dplyr:::mutate.data.frame(., col1_bigger_than_col3 = col1 > last_col())
#>   4. │ └─dplyr:::mutate_cols(.data, dplyr_quosures(...), caller_env = caller_env())
#>   5. │   ├─base::withCallingHandlers(...)
#>   6. │   └─mask$eval_all_mutate(quo)
#>   7. └─tidyselect::last_col()
#>   8.   ├─vars %||% peek_vars(fn = "last_col")
#>   9.   └─tidyselect::peek_vars(fn = "last_col")
#>  10.     └─rlang::abort(msg, call = NULL)

## output i want
dat %>%
  mutate(col1_bigger_than_col3 = col1 > col3)
#>   col1 col2 col3 col1_bigger_than_col3
#> 1    1    0    2                 FALSE
#> 2    1    1    0                  TRUE
#> 3    1    0    2                 FALSE

CodePudding user response:

We may use last_col() in select or in across

library(dplyr)
dat %>% 
   mutate(col1_bigger_than_col3 = col1 > across(last_col())[[1]])

-output

  col1 col2 col3 col1_bigger_than_col3
1    1    0    2                 FALSE
2    1    1    0                  TRUE
3    1    0    2                 FALSE

Or update with .names after doing the calculation inside across

dat %>%
   mutate(across(last_col(), ~ col1 > .x,
     .names = "col1_bigger_than_{.col}"))
  col1 col2 col3 col1_bigger_than_col3
1    1    0    2                FALSE
2    1    1    0                 TRUE
3    1    0    2                FALSE

CodePudding user response:

One way could be using the subsetted ncol function:

library(dplyr)

dat %>%
  mutate(col1_bigger_than_col3 = col1 > .[, ncol(dat)])

  col1 col2 col3 col1_bigger_than_col3
1    1    0    2                 FALSE
2    1    1    0                  TRUE
3    1    0    2                 FALSE

CodePudding user response:

Try ncol():

dat %>% 
  mutate(col1_bigger_than_col3 = col1 > .[[ncol(.)]])
#>   col1 col2 col3 col1_bigger_than_col3
#> 1    1    0    2                 FALSE
#> 2    1    1    0                  TRUE
#> 3    1    0    2                 FALSE
  • Related