-2

I have a data set something like this:

df_1 <- tribble(
  ~A,   ~B,  ~C,  
  10,   10,  NA,        
  NA,   34,  15,       
  40,   23,  NA,
   4,   12,  18,
)

Now, I just want to compare A, B, C for each row, and add a new column that shows us the minimum number. Let's see how desired data looks like:

df_2 <- tribble(
  ~A,  ~B,  ~C,  ~Winner,
  10,  10,  NA,  "Same",     
  NA,  34,  15,  "C",     
  40,  23,  NA,  "B",   
   4,  12,  18,  "A",
)

There are four outputs: Same, A-Win, B-Win, C-Win.

How would you code to get this result?

Thanks in advance.

Darren Tsai
  • 32,117
  • 5
  • 21
  • 51
datazang
  • 989
  • 1
  • 7
  • 20
  • Does this answer your question? [For each row return the column name of the largest value](https://stackoverflow.com/questions/17735859/for-each-row-return-the-column-name-of-the-largest-value) – anotherfred Nov 28 '19 at 15:46
  • What if all (A,B,C) are NA? – s_baldur Nov 28 '19 at 15:48

2 Answers2

2

Here is something:

foo <- function(x) {
  rmin <- which(x == min(x, na.rm = TRUE))
  if (length(rmin) > 1) "same" else names(rmin)
}
apply(df_1, 1,  foo)

[1] "same" "C"    "B"    "A"  

You can add this as a column to your data.frame with:

df_1$winner <- apply(df_1, 1,  foo)

# A tibble: 4 x 4
      A     B     C winner
  <dbl> <dbl> <dbl> <chr> 
1    10    10    NA same  
2    NA    34    15 C     
3    40    23    NA B     
4     4    12    18 A    

If you have more variables and only want to use some you can use a character vector:

vars <- c("A", "B", "C")
apply(df_1[vars], 1,  foo)
s_baldur
  • 29,441
  • 4
  • 36
  • 69
  • Thanks for your help. Well, this is not what I wanted to have. I've mentioned the desired output in the question. – datazang Nov 28 '19 at 16:05
  • @zineda, how does your output differ? – s_baldur Nov 28 '19 at 16:12
  • Oh, with the data.frame I could get the result. But now, another problem arose since p I've more columns in my real data than the data I've shared. And some of the variables have numerical values. :) – datazang Nov 28 '19 at 16:17
  • @zineda suggested a solution above to your new problem. – s_baldur Nov 28 '19 at 16:31
0
df_1 <- tribble(
  ~A,   ~B,  ~C,  
  10,   10,  NA,        
  NA,   34,  15,       
  40,   23,  NA,
  4,    12,  18,
)

df_1 %>%
  mutate(
    winner = colnames(df_1)[apply(df_1,1,which.min)],
    winner = if_else(A == B | B == C | A == C, 'same', winner, missing = winner))

# A tibble: 4 x 4
      A     B     C winner
  <dbl> <dbl> <dbl> <chr> 
1    10    10    NA same  
2    NA    34    15 C     
3    40    23    NA B     
4     4    12    18 A   
Metariat
  • 522
  • 3
  • 16