Skip to content

sapply Call Returning " the condition has length > 1" Error

11 messages · R. Michael Weylandt, jim holtman, John Fox +2 more

#
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 Alex,
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.
Well, you could just use
[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
[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
#
Tell us what you want to do, not how you want to do it.  What is the
problem you are trying to solve?  You can create your own
function/code within the 'apply' to process one element of the vector
as a time.  What is the output that you expect?  There is (almost)
always a way of doing it, as long as we know what you want to do.
On Tue, Dec 27, 2011 at 3:34 PM, Alex Zhang <alex.zhang at ymail.com> wrote:

  
    
#
Dear Alex,
You'll probably get a better answer if you don't keep what you want to do a
secret.
Yes. As I said, a data frame is a list of columns, so FUN is called with
each column as its argument.
I'm afraid that I don't know what you mean. Do you want to deal with the
columns of the data frame separately (in general, they need not all be of
the same class), and within each column, apply a function separately to each
element? You could nest calls to lapply() or sapply(), as in

sapply(D, function(DD) sapply(DD, abs))

assuming, of course, that D is an entirely numeric data frame. But in this
case,

abs(as.matrix(D))

would be more sensible, and using sapply() like this isn't necessarily
better than a loop. Again, not knowing what you want to do makes it hard to
suggest a solution.

Best,
 John
#
I suggest you (re-?)read the posting guide. Proper etiquette on this list is to provide a fully self-contained ("reproducible") example that demonstrates your problem. You are free to supply an alternate to your actual function as long as it illustrates your problem and you can deal with the re-substitution on your own.
---------------------------------------------------------------------------
Jeff Newmiller                        The     .....       .....  Go Live...
DCN:<jdnewmil at dcn.davis.ca.us>        Basics: ##.#.       ##.#.  Live Go...
                                      Live:   OO#.. Dead: OO#..  Playing
Research Engineer (Solar/Batteries            O.O#.       #.O#.  with
/Software/Embedded Controllers)               .OO#.       .OO#.  rocks...1k
--------------------------------------------------------------------------- 
Sent from my phone. Please excuse my brevity.
Alex Zhang <alex.zhang at ymail.com> wrote:

            
#
Jeff,

Could you please tell me which part of the guide that I didn't follow?

I provide a piece of code that can run in R, producing the problem and I also provided my results. 

Other people wanted to help me to learn more so asked me about more details. I replied very carefully explaining that i had provided all relevant information.

Jeff, before you response, did you read any of previous posts?

Sent from my iPhone
On Dec 27, 2011, at 6:19 PM, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:

            
#
Your puzzle comes from a collision of two somewhat subtle facts that
i) sapply() is a wrapper for lapply(), not apply() and ii)
data.frame()s are secretly columnwise lists. Because of this, sapply =
lapply takes each list element = data.frame column and passes it to
the column individually. Compare this behavior to

lapply(1:4, function(x)  max(x^2))

which converts its not-list input (=c(1,2,3,4)) into a list (=
list(1,2,3,4)) before processing. This is different than
lapply(list(1:4), function(x) max(x^2))

If you want to work element wise, you can work with apply() rather
than sapply(), Vectorize(), or just a plain-ol' for loop.

Does this help?

Michael

PS -- You should nag your collaborator about making a non-vectorized
function. If you got the warning message that started this all off,
there's likely a bug in his code of the if+else vs ifelse variety. If
you've never seen a document called "the R inferno" before, Google it,
and take a look through: it's full of all sorts of helpful
intermediate level tips and these sorts of subtleties are well
documented.
On Tue, Dec 27, 2011 at 4:03 PM, Alex Zhang <alex.zhang at ymail.com> wrote: