sapply with custom function (series of if statements)
Solution 1
You should be using mapply()
instead of sapply()
:
mapply(bear.correction,x,y)
Why? Your sapply()
applies bear.correction()
to each entry of x
... but giving it the entire y
vector as a second argument in each case, and so bear.correction()
only looks at the first entry in y
in all four cases. To "walk along" multiple entries in multiple vectors (or other data structures), use mapply()
.
Solution 2
You should be using mapply instead of sapply
mapply(bear.correction,x,y)
[1] 90 0 270 180
Solution 3
put a browser()
in your function like this :
bear.correction<- function(x,y){
browser()
if(x > 0 && y < 0){
return(90)
}else if(x < 0 && y < 0){
return(180)
}else if(x < 0 && y > 0){
return(270)
}else return(0)
}
you will see what give exactly as parametrs :
Browse[1]> x
[1] 1
Browse[1]> y
[1] -1 1 1 -1
So as others said here you need to use mapply
to give scalar values, not atomic vector.
but I think here using plyr
is really simpler (nice output format)
library(plyr)
dat <- data.frame(x=x,y=y)
ddply(dat,.(x,y),function(r) bear.correction(r$x,r$y))
x y V1
1 -1 -1 180
2 -1 1 270
3 1 -1 90
4 1 1 0
Solution 4
If you wish to use apply
you have to change a bit your function:
bear.correction<- function(xy){
if(xy[1] > 0 && xy[2] < 0){
return(90)
}else if(xy[1] < 0 && xy[2] < 0){
return(180)
}else if(xy[1] < 0 && xy[2] > 0){
return(270)
}else return(0)
}
The function now takes a vector of 2 values xy
and uses the first like your old x
and the second like your old y
x <- c(1,1,-1,-1)
y <- c(-1,1,1,-1)
xyx<-cbind(x,y)
apply(xyx,1, bear.correction)
Tom Evans
Seabird Ecologist. My research has mostly used GPS tracking to follow foraging behaviour in seabirds. I usually analyse this data with R.
Updated on June 07, 2022Comments
-
Tom Evans almost 2 years
I want to run a function which looks at two vectors, returning different values depending on the signs of the values in the two vectors. I have written a function which works to compare two values, but then I want to run this on two vectors. So I used sapply, but I am getting different results than expected.
bear.correction<- function(x,y){ if(x > 0 && y < 0){ return(90) }else if(x < 0 && y < 0){ return(180) }else if(x < 0 && y > 0){ return(270) }else return(0) }
The following give the expected (and desired) result:
bear.correction(1,-1) bear.correction(1,1) bear.correction(-1,1) bear.correction(-1,-1)
Result: 90, 0, 270, 180
However when I try to do the same comparisons, but using vectors with sapply I get a different result:
x <- c(1,1,-1,-1) y <- c(-1,1,1,-1) sapply(x,bear.correction,y)
Result: 90, 90, 180, 180.
I can't see what's wrong, so please help!
-
Tom Evans over 11 yearsThanks Stephan. Good answer and clear explanation. I wasn't aware of mapply()
-
Tom Evans over 11 yearsThanks, quick and succinct. Stephen gave a nice explanation too.
-
Tom Evans over 11 yearsThanks, it's useful to have the debugging advice. The Pylr alternative is nice too. I haven't used pylr much, but it's a good package.
-
Tom Evans over 11 yearsThanks. This is a nice solution too.
-
Gago-Silva over 11 yearsFor future reference on *apply functions check this question
-
Tom Evans over 11 yearsThanks. That's a really helpful resource. I will bookmark that.