daniela
daniela

Reputation: 11

ifelse() with unexpected results in R

I have a several bins in my data frame.

[1] "bin1" "bin2" "bin3" "bin4" "bin5" "bin6"

I have a bin number, and would like to exclude everything EXCEPT that bin and the previous bin. If bin=1, I would only like to exclude everything except bin1 (bin0 does not exist). To produce a vector of names of bins to exclude later from my data frame, I produce:

BinsToDelete <- ifelse(i>1, paste("bin",1:6,sep="")[-((i-1):i)],paste("bin",1:6,sep="")[-i])

For ease of understanding

> i=3
> paste("bin",1:6,sep="")[-((i-1):i)]
[1] "bin1" "bin4" "bin5" "bin6"
> paste("bin",1:6,sep="")[-i]
[1] "bin1" "bin2" "bin4" "bin5" "bin6"

Weirdly an ifelse statement produces this:

> i=3
> BinsToDelete <- ifelse(i==1, paste("bin",1:6,sep="")[-i],paste("bin",1:6,sep="")[-((i-1):i)])
> BinsToDelete
[1] "bin1"

What happened there?

A normal if-else statement gives the desired results:

> if(i==1){
  BinsToDelete <- paste("bin",1:6,sep="")[-i]
} else { BinsToDelete <- paste("bin",1:6,sep="")[-((i-1):i)]}
> BinsToDelete
[1] "bin1" "bin4" "bin5" "bin6"

Thanks for helping me understand how ifelse arrives to this conclusion.

Upvotes: 0

Views: 213

Answers (2)

IRTFM
IRTFM

Reputation: 263301

I generally avoid ifelse when possible because I think the resulting code is aesthetically unpleasing. The fact that it removes class attributes and makes handling factors and Dates and data-times difficult is a further reason to avoid it. The grep` funciton is designed to return a vector suitable for indexed selection:

> z=3
> grep( paste0("bin",(z-1):z, collapse="|") , x)
[1] 2 3
> x[ grep( paste0("bin",(z-1):z, collapse="|") , x)]
[1] "bin2" "bin3"
> z=1
> x[ grep( paste0("bin",(z-1):z, collapse="|") , x)]
[1] "bin1"

My understanding is that the dplyr if_else function addresses some of those issues.

Upvotes: 1

Gavin Simpson
Gavin Simpson

Reputation: 174788

From ?ifelse

Value:

     A vector of the same length and attributes (including dimensions
     and ‘"class"’) as ‘test’ and data values from the values of ‘yes’
     or ‘no’.

In your case:

> i <- 3
> length(i)
[1] 1

So you got a length 1 output

Upvotes: 2

Related Questions