0

I want to create a new variable c. Step 1, if a=1 then c=1 (regardless of b); step 2, if a=2 or b=2, then c=2.

a <- c (2, 2, 2, NA, NA, NA, 1, 1, 1)
b <- c (1, 2, NA, 1, 2, NA, 1, 2, NA)
ab <- data.frame (a, b)
abc <- ab %>% 
    mutate (c = ifelse (a == 1, 1, NA)) %>% 
    mutate (c = ifelse (a == 2 | b == 2, 2, c))

abc
   a  b  c
1  2  1  2
2  2  2  2
3  2 NA  2
4 NA  1 NA
5 NA  2  2
6 NA NA NA
7  1  1  1
8  1  2  2
9  1 NA NA

I expect c to be (2,2,2,NA,2,NA,1,2,1), but the actual out put is (2,2,2,NA,2,NA,1,2,NA). Why is the last cell changed to be NA (it should be 1)?

wlj
  • 25
  • 2
  • 2
    Try `ifelse(a ==1, 1, ifelse(a == 2 | b == 2, 2, NA))`. Also why *row: 8* becomes 2? The first condition is `a == 1`...? The last cell changes because in the second `ifelse` you do not have a condition for `a == 1`. It only checks for `a == 2` or `b == 2` – Sotos Jul 23 '19 at 11:02
  • Possible duplicate of [Direct way of telling ifelse to ignore NA](https://stackoverflow.com/questions/44410704/direct-way-of-telling-ifelse-to-ignore-na) – jay.sf Jul 23 '19 at 11:08
  • The documentation for ifelse states that it will return `Where condition is TRUE, the matching value from true, where it's FALSE, the matching value from false, otherwise NA`. Since b ==2 in the second mutate evaluates to NA for last row thus the NA in result. However in case of comment by Sotos it will never do this evaluation and thus not have an NA. – pd321 Jul 23 '19 at 11:14
  • Then put the conditions the other way around... – Sotos Jul 23 '19 at 11:18

1 Answers1

1

This seems like a good place for case_when, which evaluates each case until it finds one that's TRUE. It sounds like the two conditions should be swapped if you want row 8 to be 2.

library(dplyr)
abc <- ab %>%
  mutate(c = case_when(a == 2 | b == 2 ~ 2,
                       a == 1          ~ 1,
                       TRUE            ~ NA_real_))

#> abc
#   a  b  c
#1  2  1  2
#2  2  2  2
#3  2 NA  2
#4 NA  1 NA
#5 NA  2  2
#6 NA NA NA
#7  1  1  1
#8  1  2  2
#9  1 NA  1
Jon Spring
  • 55,165
  • 4
  • 35
  • 53
  • The answer is what I want but I still want to know, why Row#8 turns out to be 1 when fitting the second condition? Many thanks. – wlj Jul 23 '19 at 11:44
  • In your original code, looking at row 8, the first condition would be `TRUE` and make c = 1. Then the 2nd condition also `TRUE`, so that'd override the prior assignment and make c = 2. In the `case_when` statement here, it looks for the first TRUE and then stops. – Jon Spring Jul 23 '19 at 11:52