2

I have a data frame which contains some values. And now I would like to keep only the max value in each row and give 0 to the rest column, like this:

df <-  data_frame(a= c(1,2,3,4,5),b= c(2,5,3,9,7),c= c(40,6,2,1,7))
df$rowmax <- apply(df,1,max)
#
      a     b     c rowmax
  <dbl> <dbl> <dbl>  <dbl>
     1     2    40     40
     2     5     6      6
     3     3     2      3
     4     9     1      9
     5     7     7      7
#ideal out put
     a     b     c    rowmax
     0     0     40    40
     0     0     6     6
     3     3     0     3
     0     9     0     9
     0     7     7     7

Could any one help me out here? thanks ; )

Codezy
  • 662
  • 5
  • 17

2 Answers2

3

It may be more efficient to use pmax to get the row wise max, then select the columns of interset in mutate_at and replace the values in each column not equal to 0

library(dplyr)
library(purrr)
df %>% 
   mutate(rowmax = reduce(., pmax)) %>% 
   #or as  @tmfmnk mentioned in the comments
   # mutate(rowmax = exec(pmax, !!!.)) %>%
   mutate_at(vars(a:c), ~ replace(., .!= rowmax, 0))
   #Or do a multiplication
   #mutate_at(vars(a:c), ~. * (.== rowmax))

Also, if we don't need the rowmax column, a base R option is

df * (df == do.call(pmax, df))
akrun
  • 874,273
  • 37
  • 540
  • 662
  • 1
    It is not worth of a separate post, but a possibility for the first step could also be `mutate(rowmax = exec(pmax, !!!.))`. – tmfmnk Jul 30 '19 at 13:35
  • @akrun I follow your commands and answers and you mostly use dots inside the functions as in this answer like `reduce(., pmax)` or `replace(., .!= rowmax, 0)`. What are those dots standing for? A syntax or a shorthand? – maydin Jul 30 '19 at 13:38
  • 1
    @maydin. In the first case, `reduce`, it refers to the whole dataset coming from the lhs of `%>%`, Within `mutate_at/summarise_at/summarise_if/mutate_if/transmute_if/at/filter_at/filter_if`, it refers to individual column. It is more like `lapply(df1, function(x) x)` – akrun Jul 30 '19 at 13:40
  • @akrun I have a question. If there is another column in character in this data set, is there any way to handle this task in a tidyverse way? – jazzurro Jul 30 '19 at 15:51
  • @jazzurro How are you? I didn't get the question clearly. Here, all the columns are reduced to get the `max` per row. Did you meant another set of columns? – akrun Jul 30 '19 at 16:03
  • @akrun Sorry for taking your time. The data set in this question contains numeric columns only. I am considering a data set like this but with another column. Let's say a column with personal names as a first column. In this case, I think we need to remove the character/factor column to use pmax. Is there any way to achieve the same result like you provided with this kind of data set? In my way, I create a new column including a max value with `df$rowmax <- do.call(pmax, df[ , -1])`. Then, I will replace non-max values. I particularly wonder if that do.call line can be involved in mutate(). – jazzurro Jul 30 '19 at 16:15
  • @jazzurro That we can do with `select` `df$newCol <- "A"; df %>% mutate(rowmax = reduce(select_if(., is.numeric), pmax))`. `select_if` specifically selects the numeric column. and if you have to select columns based on column name pattern or index, either `select` or `select_at` may work – akrun Jul 30 '19 at 16:22
  • 1
    @akrun I understood. Thanks a lot for your advice. I think I will be around SO this summer while I am off from teaching. See you around. – jazzurro Jul 30 '19 at 16:28
  • @jazzurro Glad to help you. and great to see you around here – akrun Jul 30 '19 at 16:29
2

A base option:

sweep(df, 1, apply(df, 1, max), FUN = function(x, y) x * (x == y))

Output:

  a b  c
1 0 0 40
2 0 0  6
3 3 3  0
4 0 9  0
5 0 7  7
arg0naut91
  • 14,574
  • 2
  • 17
  • 38
  • it looks quiet cool! Thanks. Could you please tell me a little bit about x * (x == y)? I did not get it. – Codezy Jul 30 '19 at 13:45
  • We just multiply each element of the row with either 0 (if it is not equal to row maximum - the outcome of `x == y` is `FALSE`) or 1 (if it is equal - the outcome is `TRUE`) – arg0naut91 Jul 30 '19 at 13:48