Alex Zhang
2011-Dec-27 19:14 UTC
[R] sapply Call Returning " the condition has length > 1" Error
Dear all,
Happy new year!
I have a question re using sapply. Below is a dummy example that would replicate
the error I saw.
##Code Starts here
DummyFunc <- function(x) {
if (x > 0) {
return (x)
} else
{
return (-x)
}
}
Y = data.frame(val = c(-3:7))
sapply(Y, FUN = DummyFunc)
##Code ends here
When I run it, I got:
val
[1,] 3
[2,] 2
[3,] 1
[4,] 0
[5,] -1
[6,] -2
[7,] -3
[8,] -4
[9,] -5
[10,] -6
[11,] -7
Warning message:
In if (x > 0) { :
the condition has length > 1 and only the first element will be used
The result is different from what I would expect plus there is such an error
message.
I guess if the DummyFunc I provided is compatible with vectors, the problem
would go away. But let's suppose I cannot change DummyFunc. Is there still a
way to use sapply or alike without actually writing a loop? Thanks.
- Alex
[[alternative HTML version deleted]]
R. Michael Weylandt
2011-Dec-27 20:04 UTC
[R] sapply Call Returning " the condition has length > 1" Error
You are right that the problem is that "DummyFunc" isn't vectorized. R looks for a single logical value in an "if" statement but "x>0" gives it a whole vector's worth -- as the warning indicates, it only uses the first and pushes the whole vector through the loop in the return(-x) branch, which explains the values you saw. The correct way to do it would be something like: ifelse(x < 0, -x, x) If, as you suggest, you can't modify the function (for whatever reason), you can use the higher-order-function Vectorize() as follows: vDummyFunc <- Vectorize(DummyFunc) vDummyFunc(-3:7) This isn't real vectorization, but it hides some *apply family stuff nicely. Note that this doesn't act as you might expect on Y since data.frames are taken column wise by default (you'll get the same problem). Michael On Tue, Dec 27, 2011 at 1:14 PM, Alex Zhang <alex.zhang at ymail.com> wrote:> Dear all, > > Happy new year! > > I have a question re using sapply. Below is a dummy example that would replicate the error I saw. > > ##Code Starts here > DummyFunc <- function(x) { > > if (x > 0) { > return (x) > } else > { > return (-x) > } > > } > > Y = data.frame(val = c(-3:7)) > sapply(Y, FUN = DummyFunc) > ##Code ends here > > When I run it, I got: > ? ? ?val > ?[1,] ? 3 > ?[2,] ? 2 > ?[3,] ? 1 > ?[4,] ? 0 > ?[5,] ?-1 > ?[6,] ?-2 > ?[7,] ?-3 > ?[8,] ?-4 > ?[9,] ?-5 > [10,] ?-6 > [11,] ?-7 > Warning message: > In if (x > 0) { : > ? the condition has length > 1 and only the first element will be used > > The result is different from what I would expect plus there is such an error message. > > I guess if the DummyFunc I provided is compatible with vectors, the problem would go away. But let's suppose I cannot change DummyFunc. Is there still a way to use sapply or alike without actually writing a loop? Thanks. > > - Alex > ? ? ? ?[[alternative HTML version deleted]] > > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >
John Fox
2011-Dec-27 20:10 UTC
[R] sapply Call Returning " the condition has length > 1" Error
Dear Alex,> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r- > project.org] On Behalf Of Alex Zhang > Sent: December-27-11 2:14 PM > To: r-help at r-project.org > Subject: [R] sapply Call Returning " the condition has length > 1" > Error > > Dear all, > > Happy new year! > > I have a question re using sapply. Below is a dummy example that would > replicate the error I saw. > > ##Code Starts here > DummyFunc <- function(x) { > > if (x > 0) { > return (x) > } else > { > return (-x) > } > > } > > Y = data.frame(val = c(-3:7)) > sapply(Y, FUN = DummyFunc) > ##Code ends here > > When I run it, I got: > val > [1,] 3 > [2,] 2 > [3,] 1 > [4,] 0 > [5,] -1 > [6,] -2 > [7,] -3 > [8,] -4 > [9,] -5 > [10,] -6 > [11,] -7 > Warning message: > In if (x > 0) { : > the condition has length > 1 and only the first element will be used > > The result is different from what I would expect plus there is such an > error message.This is a warning, not really an error message. A data frame is essentially a list of variables (columns), and sapply() applies its FUN argument to each list element, that is, each variable -- the one variable val in your case. That produces a warning because val > 0 is a vector of 11 elements, and the first comparison, 3 > 0, which is TRUE, controls the result.> > I guess if the DummyFunc I provided is compatible with vectors, the > problem would go away. But let's suppose I cannot change DummyFunc. Is > there still a way to use sapply or alike without actually writing a > loop? Thanks.Well, you could just use> abs(Y$val)[1] 3 2 1 0 1 2 3 4 5 6 7 but I suppose that you didn't really want to write your own version of the absolute-value function as something more than an exercise. An alternative is> with(Y, ifelse(val > 0, val, -val))[1] 3 2 1 0 1 2 3 4 5 6 7 I hope this helps, John -------------------------------- John Fox Senator William McMaster Professor of Social Statistics Department of Sociology McMaster University Hamilton, Ontario, Canada http://socserv.mcmaster.ca/jfox> > - Alex > [[alternative HTML version deleted]]