8

Before someone marks this question as duplicate, I have already seen this one and it does not solve my question. If I try

mtcars %>% mutate(new = rowMeans(select(.,c(1,7)), na.rm = TRUE))

it works nicely, but if I do the same with pmax instead of rowMeans:

mtcars %>% mutate(new = pmax(select(.,c(1,7)), na.rm = TRUE))

I get

Error: Column `new` is of unsupported class data.frame

Why? In this example, I can get the output with

mtcars %>% mutate(new = pmax(mpg,qsec,carb,na.rm = TRUE))

but I try to use select since I need for my real data either some select helper or variables determined by column position (like 1,7 in the example), and otherwise I also get errors.

As suggested in an answer in the linked question I also tried to use do.call obtaining an error too.

Thank you!

Sotos
  • 51,121
  • 6
  • 32
  • 66
iago
  • 2,990
  • 4
  • 21
  • 27
  • Is `mtcars %>% mutate(a = apply(select(., c(1, 7)), 1, max))` sufficently dplyr? – Hugh Sep 04 '19 at 15:19
  • The issue is not `dplyr`, but the efficiency. For big datasets, `apply` combined with `max` is not so fast and efficient. In fact, it was the previous version of the code that I was tidying, and I was doing it because R was hang up there. – iago Sep 05 '19 at 09:11
  • dplyr now includes the c_across function that allows you to use select helpers like starts_with and ends_with – GGAnderson Apr 07 '23 at 20:04

3 Answers3

7

Using do.call we can evaluate pmax without specifying the variables, i.e.

mtcars %>% 
  mutate(new = do.call(pmax, c(select(., c(1, 7)), na.rm = TRUE)))

#    mpg cyl  disp  hp drat    wt  qsec vs am gear carb   new
#1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 21.00
#2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 21.00
#3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 22.80
#4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 21.40
#5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 18.70
#6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 20.22
#7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.84
#...
Sotos
  • 51,121
  • 6
  • 32
  • 66
  • Preserving row names `cbind(mtcars, new=do.call(pmax, mtcars[c(1, 7)]))`. – jay.sf Sep 04 '19 at 12:47
  • @jay.sf or just don't do it via `dplyr`.. :p (tibbles and rownames dont mix) – Sotos Sep 04 '19 at 12:50
  • Thank you! I had tried something similar, but with `args = list` instead of `args = c` (since in `do.call` help, argument `args` is described as a list), obtaining ``Error: Column `new` is of unsupported class data.frame`` too – iago Sep 04 '19 at 12:54
3

Here is one option using purrr::pmap_dbl

library(dplyr)
mtcars %>% mutate(new = purrr::pmap_dbl(select(., c(1, 7)), pmax, na.rm=TRUE))

   mpg cyl  disp  hp drat    wt  qsec vs am gear carb   new
1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 21.00
2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 21.00
3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 22.80
4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 21.40
5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 18.70
6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 20.22
7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.84
...
A. Suliman
  • 12,923
  • 5
  • 24
  • 37
3

We can use pmaxby converting column names to symbols and then evaluate (!!!)

library(dplyr)
mtcars %>%
     mutate(new = pmax(!!! rlang::syms(names(.)[c(1, 7)])))
#  mpg cyl  disp  hp drat    wt  qsec vs am gear carb   new
#1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 21.00
#2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 21.00
#3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 22.80
#4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 21.40
#5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 18.70
#6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 20.22
#7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.84

Or another option is reduce

library(purrr)
mtcars %>%
      mutate(new = reduce(select(., c(1, 7)), pmax))
akrun
  • 874,273
  • 37
  • 540
  • 662
  • I was trying to do something similar to your first proposal with `rowSums` instead of `pmax` but it doesn't work. The attempt is:`mtcars %>% mutate(new = rowSums(!!! rlang::syms(names(.)[c(1, 7)]), na.rm = T))`. Do you know why? And how should this be adatped? – iago Sep 17 '19 at 10:02
  • I do not ask the question in SO because I can avoid this problem using `select`, but I am curious if there is an alternative with `!!!rlang::syms`. Thank you! – iago Sep 17 '19 at 10:06
  • @iago If you need the `rowSums`, just do `mutate(new = rowSums(.[c(1, 7)], na.rm = TRUE))` – akrun Sep 17 '19 at 15:51