[R] How to use curve() function without using x as the variable name inside expression?
Ben Tupper
ben.bighair at gmail.com
Sat Jan 31 15:39:16 CET 2015
Hi Philippe,
Ah! Thanks for pointing out the pesky ifelse() issue. I have only recently been learning (the hard way) that ifelse() is not a tool for the uninformed like me, but it is ever so tempting!
I would like to offer another way to speed things up. findInterval() can be quite fast, and the speed up is most noticeable when the size of the input grows (note I made input x <- 1:3000).
func <- function (x, mn, mx) 1/(mx-mn) * (x >= mn & x <= mx)
funcIfElse <- function (x, mn, mx) ifelse(x < mn | x > mx, 0, 1/(mx - mn))
funcFindInterval <- function(x, mn, mx) 1/(mx - mn) * (findInterval(x, c(mn, mx), rightmost.closed = TRUE) == 1)
mn<- 100; mx <- 200; x <- 1:3000
microbenchmark::microbenchmark(func(x, mn, mx), funcIfElse(x, mn, mx), funcFindInterval(x, mn, mx))
#Unit: microseconds
# expr min lq mean median uq max neval
# func(x, mn, mx) 74.920 76.006 88.57119 76.5635 78.7065 897.333 100
# funcIfElse(x, mn, mx) 728.388 733.206 832.02225 735.4280 796.1910 1645.804 100
# funcFindInterval(x, mn, mx) 33.954 35.334 56.57323 36.5010 38.3340 993.193 100
r1 <- func(x, mn, mx)
r2 <- funcIfElse(x, mn, mx)
r3 <- funcFindInterval(x, mn, mx)
identical(r1, r2)
#[1] TRUE
identical(r2, r3)
#[1] TRUE
Cheers,
Ben
On Jan 31, 2015, at 4:03 AM, Philippe Grosjean <phgrosjean at sciviews.org> wrote:
> Also note that ifelse() should be avoided as much as possible. To define a piecewise function you can use this trick:
>
> func <- function (x, min, max) 1/(max-min) * (x >= min & x <= max)
>
> The performances are much better. This has no impact here, but it is a good habit to take in case you manipulate such kind of functions in a more computing-intensive context (numerical integration, nls(), etc.).
>
> funcIfElse <- function (x, min, max) ifelse(x < min | x > max, 0, 1/(max - min))
> min <- 100; max <- 200; x <- 1:300
> microbenchmark::microbenchmark(func(x, min, max), funcIfElse(x, min, max))
> ## Unit: microseconds
> ## expr min lq mean median uq max neval
> ## func(x, min, max) 10.242 16.0175 18.43348 18.446 19.8680 47.266 100
> ## funcIfElse(x, min, max) 90.386 125.1605 148.18555 143.455 148.6695 1203.292 100
>
> Best,
>
> Philippe Grosjean
>
>> On 31 Jan 2015, at 09:39, Rolf Turner <r.turner at auckland.ac.nz> wrote:
>>
>> On 31/01/15 21:10, C W wrote:
>>> Hi Bill,
>>>
>>> One quick question. What if I wanted to use curve() for a uniform
>>> distribution?
>>>
>>> Say, unif(0.5, 1.3), 0 elsewhere.
>>>
>>> My R code:
>>> func <- function(min, max){
>>> 1 / (max - min)
>>> }
>>>
>>> curve(func(min = 0.5, max = 1.3), from = 0, to = 2)
>>>
>>> curve() wants an expression, but I have a constant. And I want zero
>>> everywhere else.
>>
>> Well if that's what you want, then say so!!!
>>
>> func <- function(x,min,max) {
>> ifelse(x < min | x > max, 0, 1/(max - min))
>> }
>>
>> curve(func(u,0.5,1.3),0,2,xname="u")
>>
>> Or, better (?) curve(func(u,0.5,1.3),0,2,xname="u",type="s")
>>
>> which avoids the slight slope in the "vertical" lines.
>>
>> cheers,
>>
>> Rolf Turner
>>
>> --
>> Rolf Turner
>> Technical Editor ANZJS
>> Department of Statistics
>> University of Auckland
>> Phone: +64-9-373-7599 ext. 88276
>> Home phone: +64-9-480-4619
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> 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 -- To UNSUBSCRIBE and more, see
> 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.
More information about the R-help
mailing list