Reputation: 12550
I wrote a somewhat grotesque function, which should simply return a vector with two values.
For example, if you put in 33
, you should get back c(30, 40)
.
It couldn't get much simpler than this.
return_a_range <- function(number){
ans <- ifelse( (30 <= number & number <= 40), c(30, 40),
(ifelse( (40 < number & number <= 50), c(40, 50),
(ifelse( (50 < number & number <= 60), c(50, 60),
(ifelse( (60 < number & number <= 70), c(60, 70),
(ifelse( (70 < number & number <= 80), c(70, 80),
(ifelse( (80 < number & number <= 100), c(80, 100),
ans <- c("NA"))))))))))))
return(ans)}
return_a_range(33)
Why is this returning only 30
? How am I not getting back c(30, 40)
? Why did R decide to only return the value in the first position of the vector?
EDIT
Although most of the responses are concerned with (justifiably!) spanking me for writing a lousy ifelse
statement, I think the real question was recognized and answered best by @MrFick in the comments directly below.
Upvotes: 4
Views: 775
Reputation: 70266
You could just use:
> c(floor(33 / 10), ceiling(33 / 10))*10
[1] 30 40
Or as a function - thanks to @Khashaa for a nice modification (in the comments):
f <- function(x) if(abs(x) >= 100) NA else c(floor(x / 10), floor(x/10) + 1)*10
f(44)
#[1] 40 50
f(40)
#[1] 40 50
This kind of functions will be a lot more efficient than multiple nested ifelse
s.
I overlooked initially that you want to return 30 - 40 for a input value of 40 (I thought you wanted 40 - 50 which is what the above function does).
So this is a slightly more elaborate function which should implement that behavior:
ff <- function(x) {
if (abs(x) >= 100L) {
NA
} else {
y <- floor(x / 10L) * 10L
if (x %% 10L == 0L) {
c(y - 10L, y)
} else {
c(y, y + 10L)
}
}
}
And in action:
ff(40)
#[1] 30 40
ff(45)
#[1] 40 50
Or if you had a vector of numbers you could lapply/sapply over it:
( x <- sample(-100:100, 3, F) )
#[1] 73 89 -97
lapply(x, ff)
#[[1]]
#[1] 70 80
#
#[[2]]
#[1] 80 90
#
#[[3]]
#[1] -100 -90
Or
sapply(x, ff)
# [,1] [,2] [,3]
#[1,] 70 80 -100
#[2,] 80 90 -90
Upvotes: 4
Reputation: 92292
Here's another variation using %/%
which will work for f2(40)
case too (but my fail somewhere else?)
f2 <- function(x) if(abs(x) >= 100) NA else c(x %/% 10, (x + 10) %/% 10) * 10
f2(40)
## [1] 40 50
Upvotes: 2
Reputation: 37879
If you really want to use your function the way you use it and not go with docendo's answer (where for this problem I don't see why) you can do the following (in case you need to do something similar in the future):
return_a_range <- function(number){
ans <- ifelse( (30 <= number & number <= 40), a<-c(30, 40),
(ifelse( (40 < number & number <= 50), a<-c(40, 50),
(ifelse( (50 < number & number <= 60), a<-c(50, 60),
(ifelse( (60 < number & number <= 70), a<-c(60, 70),
(ifelse( (70 < number & number <= 80), a<-c(70, 80),
(ifelse( (80 < number & number <= 100), a<-c(80, 100),
a <- c("NA"))))))))))))
return(a)}
> return_a_range(33)
[1] 30 40
> return_a_range(62)
[1] 60 70
The only thing I did was to save the vector in a variable a
on each ifelse
.
Upvotes: 1