An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111227/e25b41d1/attachment.pl>
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 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.
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]]
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111227/92c96c1e/attachment.pl>
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:
John, Thanks for the pointers. The DummyFunc is just a made-up example. The true function I need to use is more complicated and would be?distractive to include. Do you mean that sapply would take columns in the input data.frame and feed them into "FUN" as "whole" vectors? That explains the behavior. Is there an "*apply" function that will fee elements of the input data.frame into "FUN" instead of whole columns? Thanks.
________________________________
?From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 3:10 PM
Subject: RE: [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]]
? ? ? ?[[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.
Jim Holtman Data Munger Guru What is the problem that you are trying to solve? Tell me what you want to do, not how you want to do it.
Dear Alex,
-----Original Message----- From: Alex Zhang [mailto:alex.zhang at ymail.com] Sent: December-27-11 3:34 PM To: John Fox Cc: r-help at r-project.org Subject: Re: [R] sapply Call Returning " the condition has length > 1" Error John, Thanks for the pointers. The DummyFunc is just a made-up example. The true function I need to use is more complicated and would be distractive to include.
You'll probably get a better answer if you don't keep what you want to do a secret.
Do you mean that sapply would take columns in the input data.frame and feed them into "FUN" as "whole" vectors? That explains the behavior.
Yes. As I said, a data frame is a list of columns, so FUN is called with each column as its argument.
Is there an "*apply" function that will fee elements of the input data.frame into "FUN" instead of whole columns? Thanks.
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
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 3:10 PM
Subject: RE: [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]]
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111227/7e207a6f/attachment.pl>
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:
John, Thank you for your comment.? There is no secret. But the actual function I need to call is rather irrelevant.?However don't take it as the "abs" function. If you like to know, it is a function that converts 4 kinds of old ids from several old database tables into a new id in a new database. Again, I don't think providing?such detail is better than saying MyDummyFunc maps a number into a number but doesn't work?with vectors. All I need to do, is to call DummyFunc for every element in a column of a data.frame and returns?the resulted vector. But, I cannot change DummyFunc. Correct me if I am wrong: this is rather?common in a group?collaboration enviroment. Person A may be responsible for writing a function and person B who needs to use that function cannot or better not change it. Obviously, I could write a loop. Michael in a previous post suggested using vectorize which works perfectly. As a newbie of R, I would wish to learn more ways to achieve my goal (sorry, it automatically involves "how" not just "what" ;). Is there a way using?a "*apply" function to do it where * stands for any function. Thanks a lot!?
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 4:06 PM
Subject: RE: [R] sapply Call Returning " the condition has length > 1"
Error
Dear Alex,
-----Original Message-----
From: Alex Zhang [mailto:alex.zhang at ymail.com]
Sent: December-27-11 3:34 PM
To: John Fox
Cc: r-help at r-project.org
Subject: Re: [R] sapply Call Returning " the condition has length >
1"
Error
John,
Thanks for the pointers.
The DummyFunc is just a made-up example. The true function I need to
use is more complicated and would be distractive to include.
You'll probably get a better answer if you don't keep what you want to
do a
secret.
Do you mean that sapply would take columns in the input data.frame
and
feed them into "FUN" as "whole" vectors? That explains the behavior.
Yes. As I said, a data frame is a list of columns, so FUN is called
with
each column as its argument.
Is there an "*apply" function that will fee elements of the input
data.frame into "FUN" instead of whole columns? Thanks.
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
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 3:10 PM
Subject: RE: [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]]
[[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.
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:
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:
John, Thank you for your comment.? There is no secret. But the actual function I need to call is rather irrelevant.?However don't take it as the "abs" function. If you like to know, it is a function that converts 4 kinds of old ids from several old database tables into a new id in a new database. Again, I don't think providing?such detail is better than saying MyDummyFunc maps a number into a number but doesn't work?with vectors. All I need to do, is to call DummyFunc for every element in a column of a data.frame and returns?the resulted vector. But, I cannot change DummyFunc. Correct me if I am wrong: this is rather?common in a group?collaboration enviroment. Person A may be responsible for writing a function and person B who needs to use that function cannot or better not change it. Obviously, I could write a loop. Michael in a previous post suggested using vectorize which works perfectly. As a newbie of R, I would wish to learn more ways to achieve my goal (sorry, it automatically involves "how" not just "what" ;). Is there a way using?a "*apply" function to do it where * stands for any function. Thanks a lot!?
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 4:06 PM
Subject: RE: [R] sapply Call Returning " the condition has length > 1"
Error
Dear Alex,
-----Original Message-----
From: Alex Zhang [mailto:alex.zhang at ymail.com]
Sent: December-27-11 3:34 PM
To: John Fox
Cc: r-help at r-project.org
Subject: Re: [R] sapply Call Returning " the condition has length >
1"
Error
John,
Thanks for the pointers.
The DummyFunc is just a made-up example. The true function I need to
use is more complicated and would be distractive to include.
You'll probably get a better answer if you don't keep what you want to
do a
secret.
Do you mean that sapply would take columns in the input data.frame
and
feed them into "FUN" as "whole" vectors? That explains the behavior.
Yes. As I said, a data frame is a list of columns, so FUN is called
with
each column as its argument.
Is there an "*apply" function that will fee elements of the input
data.frame into "FUN" instead of whole columns? Thanks.
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
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 3:10 PM
Subject: RE: [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]]
[[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.
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:
John, Thank you for your comment. There is no secret. But the actual function I need to call is rather irrelevant.?However don't take it as the "abs" function. If you like to know, it is a function that converts 4 kinds of old ids from several old database tables into a new id in a new database. Again, I don't think providing?such detail is better than saying MyDummyFunc maps a number into a number but doesn't work?with vectors. All I need to do, is to call DummyFunc for every element in a column of a data.frame and returns?the resulted vector. But, I cannot change DummyFunc. Correct me if I am wrong: this is rather?common in a group?collaboration enviroment. Person A may be responsible for writing a function and person B who needs to use that function cannot or better not change it. Obviously, I could write a loop. Michael in a previous post suggested using vectorize which works perfectly. As a newbie of R, I would wish to learn more ways to achieve my goal (sorry, it automatically involves "how" not just "what" ;). Is there a way using?a "*apply" function to do it where * stands for any function. Thanks a lot!
________________________________
?From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 4:06 PM
Subject: RE: [R] sapply Call Returning " the condition has length > 1" Error
Dear Alex,
-----Original Message-----
From: Alex Zhang [mailto:alex.zhang at ymail.com]
Sent: December-27-11 3:34 PM
To: John Fox
Cc: r-help at r-project.org
Subject: Re: [R] sapply Call Returning " the condition has length > 1"
Error
John,
Thanks for the pointers.
The DummyFunc is just a made-up example. The true function I need to
use is more complicated and would be distractive to include.
You'll probably get a better answer if you don't keep what you want to do a
secret.
Do you mean that sapply would take columns in the input data.frame and
feed them into "FUN" as "whole" vectors? That explains the behavior.
Yes. As I said, a data frame is a list of columns, so FUN is called with
each column as its argument.
Is there an "*apply" function that will fee elements of the input
data.frame into "FUN" instead of whole columns? Thanks.
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
________________________________
From: John Fox <jfox at mcmaster.ca>
To: 'Alex Zhang' <alex.zhang at ymail.com>
Cc: r-help at r-project.org
Sent: Tuesday, December 27, 2011 3:10 PM
Subject: RE: [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]]
? ? ? ?[[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.
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111227/61b141bc/attachment.pl>