[R] Function gives numeric(0) for every input
Joshua Wiley
jwiley.psych at gmail.com
Sun Nov 20 07:31:04 CET 2011
Hi Alex,
Michael is correct that vectorizing this is the way to go. Since this
is for class and vectorizing requires a bit of thought, I am not going
to demonstrate it with your function; however, here are some very
minor changes you can make that give fairly substantial performance
increases. It can be hard when you are learning create super
efficient code, but as a general rule of thumb (particularly when
loops are involved), byte compiling cannot hurt and may help quite a
bit, and it does not really require any extra thought or effort on
your part.
Cheers,
Josh (examples and benchmarks below)
## what you had just changing phat <- 0L
## and indenting the code and using <- instead of =
buffonslow <- function(n) {
x <- NULL
theta <- NULL
a <- NULL
phat <- 0L
i <- 1L
while (i <= n) {
x[i] <- runif(1, 0, 1/2)
theta[i] <- runif(1, 0, pi/2)
a[i] <- 1/2 * (sin(theta[i])) - x[i]
if (a[i] <= 0) phat <- phat + 1
else phat <- phat
i <- i + 1L
}
return(phat)
}
## basically what you had
## but instead of incrementally growing
## x, theta, and a (which requires R to make copies at each expansion
## instatiate them as n length vectors
buffon <- function(n) {
x <- vector("numeric", n)
theta <- vector("numeric", n)
a <- vector("numeric", n)
phat <- 0L
i <- 1L
while (i <= n) {
x[i] <- runif(1, 0, 1/2)
theta[i] <- runif(1, 0, pi/2)
a[i] <- 1/2 * (sin(theta[i])) - x[i]
if (a[i] <= 0) phat <- phat + 1
i <- i + 1L
}
return(phat)
}
## take the trivial step of byte compiling the function
require(compiler)
cbuffon <- cmpfun(buffon)
## benchmark slow and uncompiled versus compiled
## on 500 iterations
set.seed(1)
system.time(for (i in 1:500) buffonslow(i))
set.seed(1)
system.time(for (i in 1:500) buffon(i))
set.seed(1)
system.time(for (i in 1:500) cbuffon(i))
## but maybe you will not be doing many iterations
## just one large number
set.seed(1)
system.time(buffonslow(50000))
set.seed(1)
system.time(buffon(50000))
set.seed(1)
system.time(cbuffon(50000))
On my system, here are the times. Notice that just instatiating a
full sized vector yields a *huge* speedup when buffon is called for
large N. Compiling helps further.
> ## benchmark slow and uncompiled versus compiled
> ## on 500 iterations
> set.seed(1)
> system.time(for (i in 1:500) buffonslow(i))
user system elapsed
9.82 0.00 9.96
>
> set.seed(1)
> system.time(for (i in 1:500) buffon(i))
user system elapsed
8.06 0.01 8.38
>
> set.seed(1)
> system.time(for (i in 1:500) cbuffon(i))
user system elapsed
3.35 0.00 3.44
>
> ## but maybe you will not be doing many iterations
> ## just one large number
> set.seed(1)
> system.time(buffonslow(50000))
user system elapsed
89.63 0.29 93.70
> set.seed(1)
> system.time(buffon(50000))
user system elapsed
3.21 0.00 3.31
> set.seed(1)
> system.time(cbuffon(50000))
user system elapsed
1.36 0.00 1.39
On Sat, Nov 19, 2011 at 9:08 PM, R. Michael Weylandt
<michael.weylandt at gmail.com> <michael.weylandt at gmail.com> wrote:
> Also, vectorize this puppy - that's how you really get the best performance out of R, but in this case it will easily get rid of your problem.
>
> Michael
>
> On Nov 19, 2011, at 11:31 PM, Peter Langfelder <peter.langfelder at gmail.com> wrote:
>
>> Well, you assign numeric(0) or numeric(0)+1, which is still
>> numeric(0). No wonder the return value is always numeric(0).
>>
>> You probably need to replace numeric(0) simply by 0. Numeric(0) does
>> not mean 0, it means a numeric vector of length zero (i.e., empty).
>>
>> HTH,
>>
>> Peter
>>
>> On Sat, Nov 19, 2011 at 6:52 PM, alex_janssen <janssena at uoguelph.ca> wrote:
>>> Hi,
>>>
>>> I am trying to code buffons needle in R for a class
>>>
>>> This is my code w/ output from R, if anyone could tell me why this is
>>> happening it would be amazing,
>>>
>>> I can generate correct results without putting the steps into a function but
>>> alas that is the assignment.
>>>> buffon = function(n){
>>> + x = NULL
>>> + theta = NULL
>>> + a = NULL
>>> + phat = numeric(0)
>>> + i = 1
>>> +
>>> + while ( i <= n){
>>> + x[i] <- runif(1,0,1/2)
>>> + theta[i] <- runif(1,0,pi/2)
>>> + a[i] <- 1/2 * (sin(theta[i])) - x[i]
>>> +
>>> +
>>> + if (a[i] <= 0)phat <- phat + 1
>>> + else phat<-phat
>>> + i <- i + 1
>>> +
>>> + }
>>> + return(phat)
>>> + }
>>>> buffon(10)
>>> numeric(0)
>>>>
>>> Thanks Again
>>>
>>> the response should be the number of times a[i] is less than or equal to
>>> zero, which i am calling phat
>>>
>>> --
>>> View this message in context: http://r.789695.n4.nabble.com/Function-gives-numeric-0-for-every-input-tp4087834p4087834.html
>>> Sent from the R help mailing list archive at Nabble.com.
>>>
>>> ______________________________________________
>>> 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.
>>>
>>
>> ______________________________________________
>> 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.
>
> ______________________________________________
> 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.
>
--
Joshua Wiley
Ph.D. Student, Health Psychology
Programmer Analyst II, ATS Statistical Consulting Group
University of California, Los Angeles
https://joshuawiley.com/
More information about the R-help
mailing list