문제

I've got code that does what I want. I would, however, very much like to understand why it works one way and not the other.

I wanted to conditionally put new values into a new column, and wrote the following code:

test <- data.frame(Usual=c(1:3,NA,NA,4,5,7,15))

test$Active1 <- NA

test$Active1 <- ifelse(test[,"Usual"]==1|test[,"Usual"]==2|test[,"Usual"]==3,1,
                       ifelse(test[,"Usual"]==7,2,
                              ifelse(test[,"Usual"]==4|test[,"Usual"]==5|test[,"Usual"]==6|test[,"Usual"]==7,3,
                                     ifelse(is.na(test[,"Usual"]),"ROAR",":("))))

I put in the extra condition for is.na at the end, because I wasn't sure if it would get confused if I didn't do that. But it doesn't replace the NAs with "ROAR" - why?

If I put the condition for is.na at the front of the ifelse, it does what I expected it to do:

test$Active2 <- NA
  test$Active2 <- ifelse(is.na(test[,"Usual"]),"ROAR",
                         ifelse(test[,"Usual"]==7,2,
                                ifelse(test[,"Usual"]==4|test[,"Usual"]==5|test[,"Usual"]==6|test[,"Usual"]==7,3,
                                       ifelse(test[,"Usual"]==1|test[,"Usual"]==2|test[,"Usual"]==3,1,":("))))

Why does it make a difference where it's put in the ifelse? (I don't even need to use ifelse for this I know, but I was curious if it would look neater..)

도움이 되었습니까?

해결책

From the help page:

yes will be evaluated if and only if any element of test is true, and analogously for no.

In your first example, ifelse(is.na()) is never evaluated for NA rows because it fails to evaluate at the first ifelse condition.

다른 팁

This sort of question is most easily answered by simply typing ifelse in the R console, and the code used will be displayed. Studying the code will tell you what it does with NA.

R > ifelse
function (test, yes, no) 
{
    if (is.atomic(test)) {
        if (typeof(test) != "logical") 
            storage.mode(test) <- "logical"
        if (length(test) == 1 && is.null(attributes(test))) {
            if (is.na(test)) 
                return(NA)
            else if (test) {
                if (length(yes) == 1 && is.null(attributes(yes))) 
                  return(yes)
            }
            else if (length(no) == 1 && is.null(attributes(no))) 
                return(no)
        }
    }
    else test <- if (isS4(test)) 
        as(test, "logical")
    else as.logical(test)
    ans <- test
    ok <- !(nas <- is.na(test))
    if (any(test[ok])) 
        ans[test & ok] <- rep(yes, length.out = length(ans))[test & 
            ok]
    if (any(!test[ok])) 
        ans[!test & ok] <- rep(no, length.out = length(ans))[!test & 
            ok]
    ans[nas] <- NA
    ans
}
<bytecode: 0x1018abad0>
<environment: namespace:base>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top