Reputation: 563
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!
Upvotes: 10
Views: 14632
Reputation: 121568
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
Upvotes: 4
Reputation: 10629
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)
Upvotes: 3
Reputation: 8267
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()
.
Upvotes: 12
Reputation: 1961
You should be using mapply instead of sapply
mapply(bear.correction,x,y)
[1] 90 0 270 180
Upvotes: 5