I am extremely new to R, so the solution to this is probably relatively simple. I have the following function to calculate stopping distance for an average car:
distance <- function(mph){(2.0*(mph/60))+(0.062673*(mph^1.9862))}
And I'm plotting all stopping distances from 1 mph to 60 mph:
range = distance(1:60)
But I need to mark where the stopping distance is equal to 120 ft. I don't have any idea how this is done in R, but I'd like to write a function where, for a stoppingdistance(x), I get the maximum speed of the car in MPH. What function should I use, and is there an easy way to check if the value of distance(x) (as it's written above) is equal to a certain value?
One way to do it would be to find when the function -120 is equal to 0:
distance <- function(mph, dist=0){(2.0*(mph/60))+(0.062673*(mph^1.9862))-dist}
uniroot(distance, c(1, 60), dist=120)
## $root
## [1] 44.63998
##
## $f.root
## [1] -5.088982e-06
##
## $iter
## [1] 6
##
## $estim.prec
## [1] 6.103516e-05
And to see if it worked:
distance(44.63998)
## [1] 120
I know this is an old question and has an accepted answer, but I want to point out another way to accomplish this - create the inverse function. Since you have the function, it is easy to generate many x-y points over a plausible range. Then simply create the inverse function by making y be a function of x. In your example,
x = seq(0,150,0.05)
y = distance(x)
speed = approxfun(y,x)
Now let's confirm that it gives good answewrs:
speed(120)
[1] 44.63998
distance(speed(120))
[1] 120
Related
Is there any way to perform sampling using common random numbers with R?
There are many cases where you do the following many times (for instance, if you wanted to plot Monte Carlo estimates at many different parameter values). First, you sample, say, ten thousand variates from a normal distribution, and second, you take the average of some function of these samples, returning a single floating point numbers. Now, if I wanted to change a few parameters, changing either of these two functions, I would have to re-do those steps over and over again.
The naive way would be to sample fresh draws over and over again using some function like rnorm(). A less naive way would be to use a different function that takes a large collection of common random numbers. However, if I used this approach, there might still be a lot of copying going on here, due to R mostly using pass-by-value semantics. What are some tools that would allow me to get around this and avoid all this copying in the second situation?
I think you're asking two types of questions here:
Programmatically, can we preserve a large pull of random data in such a way that side-steps R's default pass-by-value?
Mathematically, if we make a large pull of random data and pick from it piece-meal, can we arbitrarily change the parameters used in the pull?
The answer to 1 is "yes": pass-by-reference semantics are possible in R, but they take a little more work. All of the implementations I've seen and played with are done with environments or non-R-native objects (C/C++ pointers to structs or such). Here is one example that caches a large pull of random "normal" data and checks the pool of available data on each call:
my_rnorm_builder <- function(deflen = 10000) {
.cache <- numeric(0)
.index <- 0L
.deflen <- deflen
check <- function(n) {
if ((.index + n) > length(.cache)) {
message("reloading") # this should not be here "in-production"
l <- length(.cache)
.cache <<- c(.cache[ .index + seq_len(l - .index) ],
rnorm(.deflen + n + l))
.index <<- 0L
}
}
function(n, mean = 0, sd = 1) {
check(n)
if (n > 0) {
out <- mean + sd * .cache[ .index + seq_len(n) ]
.index <<- .index + as.integer(n)
return(out)
} else return(numeric(0))
}
}
It is by-far not resilient to hostile users or other likely mistakes. It does not guarantee the length of available remaining random numbers. (To put in checks like that would slow it down below a threshold of reasonable-ness, with the benchmark in mind.)
Demo of it in operation:
my_rnorm <- my_rnorm_builder(1e6)
# starts empty
get(".index", env=environment(my_rnorm))
# [1] 0
length(get(".cache", env=environment(my_rnorm)))
# [1] 0
set.seed(2)
my_rnorm(3) # should see "reloading"
# reloading
# [1] -0.8969145 0.1848492 1.5878453
my_rnorm(3) # should not see "reloading"
# [1] -1.13037567 -0.08025176 0.13242028
# prove that we've changed things internally
get(".index", env=environment(my_rnorm))
# [1] 6
length(get(".cache", env=environment(my_rnorm)))
# [1] 1000003
head(my_rnorm(1e6)) # should see "reloading"
# reloading
# [1] 0.7079547 -0.2396980 1.9844739 -0.1387870 0.4176508 0.9817528
Let's make sure that the random-number scaling of sigma*x+mu makes sense by starting over and re-setting our seed:
# reload the definition of my_rnorm
my_rnorm <- my_rnorm_builder(1e6)
length(get(".cache", env=environment(my_rnorm)))
# [1] 0
set.seed(2)
my_rnorm(3) # should see "reloading"
# reloading
# [1] -0.8969145 0.1848492 1.5878453
my_rnorm(3, mean = 100) # should not see "reloading"
# [1] 98.86962 99.91975 100.13242
So to answer question 2: "yes". Quick inspection reveals that those last three numbers are indeed "100 plus" the numbers in the second my_rnorm(3) in the previous block. So just shifting "normal" random numbers by mu/sigma holds. And we did this while still using the large pre-pulled cache of random data.
But is it worth it? This is a naïve test/comparison in and of itself, constructive suggestions are welcome.
t(sapply(c(1,5,10,100,1000,10000), function(n) {
s <- summary(microbenchmark::microbenchmark(
base = rnorm(n),
my = my_rnorm(n),
times = 10000, unit = "ns"
))
c(n = n, setNames(s$median, s$expr))
}))
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# reloading
# n base my
# [1,] 1 1100 1100
# [2,] 5 1400 1300
# [3,] 10 1600 1400
# [4,] 100 6400 2000
# [5,] 1000 53100 6600
# [6,] 10000 517000 49900
(All medians are in nanoseconds.) So while it would have seemed intuitive that "smaller pulls done more frequently" (with rnorm) would have benefited from this caching, I cannot explain why it is not very helpful until pulls 100 and greater.
Can this be extended to other distributions? Almost certainly. "Uniform" would be straight forward (similarly scale and shift), but some others might take a little more calculus to do correctly. (For instance, it is not obvious without more research how the "t" distribution could alter the degrees-of-freedom on pre-pulled data ... if that's even possible. Though I do count myself a statistician in some ways, I am not prepared to claim yes/no/maybe on that one yet :-)
Addition to r2evans' answer concerning is it worth it?: I don't think so, since instead of caching random draws one could also use a faster RNG. Here I am adding dqrnorm from my dqrng package to the comparison:
dqrnorm is the fastest method for n <= 100
for n > 100, caching and dqrnorm are comparable and much faster than rnorm
I am new to programming and R and would like to compute the following sum
I used the pochMpfr from the Rmpfr package for the rising factorial and a for loop in order compute the sum.
B=rep(1,k+1)
for (i in 0:k) {
B[(i+1)]= (-1)^i *choose(k,i)*pochMpfr((-i)*sigma, n)
}
sum(B)
Doing so, I get the results as list (including always: mpfr) and thus cannot compute the sum.
Is there a possibility to get the results immediately as a Matrix or to convert the list to vector including only the relevant Elements?
The solution is probably quite easy but I haven't found it while looking through the forums.
There is no need to use a for-loop, this should work:
library(Rmpfr)
# You do not define these in your question,
# so I just take some arbitrary values
k <- 10
n <- 3
sigma <- 0.3
i <- 0:k
B <- (-1)^i *choose(k,i)*pochMpfr((-i)*sigma, n)
sum(B)
## 1 'mpfr' number of precision 159 bits
## [1] 6.2977401071861993597462780570563107354142915151e-14
I previously used the prod() function in R that can give me the product, and it works fine for big numbers. The numbers I have are too small like 1.294528e-07 and once I take the product it gives me a 0. How can I get the accurate product with exact decimal numbers?
This sounds like a job for Rmpfr:
x <- 1.294528e-07;
x^100;
## [1] 0
library('Rmpfr');
mpfr200 <- function(...) mpfr(...,precBits=200);
x <- mpfr200(1.294528e-07);
x^100;
## 1 'mpfr' number of precision 200 bits
## [1] 1.6260909947893069252110098843324246495136887016336218206204661e-689
Or you could try using big rationals from gmp, although that can get unwieldy fast:
library('gmp');
x <- as.bigq(1.294528e-07);
x^100;
## Big Rational ('bigq') :
## [1] 863201774730415899361077141424209396921125795515936990572548766128423810485376236957138978501283812494839104247698243918794530436552717763753923415271480284747830193402522833445368586578235815336302329397252055448087703163456038666698935354732741208048881276922439385153961853551463063865863458552423073323374618023089542368149617965922293453325011050815707644365808660423522776994133587512616070446174486428153909409377712433145387919387175172482342168167092570331925560436171324785600650158865676862026009729048525389272889703709380624434349438465164559591242984791355618727989751127260257309242805499481511142165616784856784942417419338154196561431152388897904866047119736434465720555151366859879507712533271194851766672024261634534292974370183919317337519761869292257947511511111895425764926171263133863980854536246390233199502174749146911367500644673909293464659053254182209374190247093969004854275674922622004129684228283369400286413197699863545912211106461047595912964876198783114172495242447965086668614473659343976994896679029656266765528726921384485164153780083326552118475505412074971594197272427677831237385443579950907872485700396062323506489811292749356021319775368577664875790645937426179486396681942844892307294288187671687510056569029216067321069225537944854772595983467728588640812585079820715315382504185719050646602130250650306723313760231069912835376365077115331890400516502810239814459239282321065702537572103441710647744406489548580900916084596895906189449738524638127337711843685456775272799845630310027842996833372802952394634016929280394482001/53084469288402965415857953902888840109250315594591772197851276288408082158869345776872184284291470495326835835491268017776297213098616208286592801322449982740570898437845767564651639451594841758957168240360072929342348878909784083488070009533176658698675760470010215436132534526706916446032842195249059760060209393388578176281027744679436285035293376786965957429093838689438026612141820062960073237944227430409290082873605748455349816343081466372681612738552636294666573661997989000563367893746123926316870120929629731301360766711677076606816082939449299471019533119911247114865751561110071173719092050562287666719013887097553109594042589835370732409680749273477741701995190365166750190649349508586781414000112900259875654673888811075100415790235930270448790550846107436360615795146817327563001398966815753145995110673462134196824939359497706430237425390060733252224220979131253874493851823165781457427314551881655553433521397260371393668335053627112038905459972042994824319713601980913921755210218082851146588240382210406887660412630451416112206306502796230074832738884324233514086958873577398927563897852887699678587467916741882087729456997268017154775450070371874680332524775280043635270781581135769020865808796073362505082201497885288236887117727248916243704472117062440908853938749830047482062530807255930310025959255017626077608884577821899189515192765061903944746945679900747890669013446056647522960607623949336195016784356934505954115977283306997415274187752372480232652878520163417566097389917356958213807994947634794209832173114356392822435844256992216702376456519427913660058510779720382422426729352627871147386069533497741201545766859622239986052843328404669795291152396764393702113455439610494964706121896827191760262984304690887475635610694078746800875955908479469409563047706020039725815572087005410536948676710051947334063697608908539017716795313119629533327813992071776512146390147185444968042597376280912548998385218672413833388480083312283356458666501168482077474943858309275329657545594008977132937574085616539588927255406484838471048801662983695044651588178399267847057683205128610922849562650411762874243138435345707386259866513245949164125352989897783775852403441398200260025840304184956928642989258546038224598392605412214974894309376
(Notice the slash at character 1570 into that digit sequence.)
I wanted to know how I can define variables in an implicit way in R.
For example, let's assume I have z<-0.5 and x<-2, I want to define y such that the following holds: z=beta(x,y).
Obviously, if I enter z<-beta(x,y), I have the following error Error in beta(x, y) : object 'y' not found.
I tried to find a solution in google but strangely I didn't find anything.
Thank you in advance!
For your example you could use uniroot to find the value of y:
(y <- uniroot(function(y) beta(x,y)-z, interval=c(0,100)))
$root
[1] 1
$f.root
[1] -1.08689e-07
$iter
[1] 13
$estim.prec
[1] 6.103516e-05
beta(x,y$root)==z
[1] FALSE
all.equal(beta(x,y$root),z, tol=1e-5)
[1] TRUE
beta(x,1)==z
[1] TRUE
However this relies on a number of assumptions such as there only being one value to satisfy the equation and you being able to give it a sensible interval. In general your function may not admit solutions, and it may be slow to compute if you need to calculate a large number of y values. You also need to consider that a numerical solution may not be exact, so comparisons will need to be made with care.
I would like to change the precision in a calculation of R. For example I would like to calculate x^6 with x = c(-2.5e+59, -5.6e+60). In order to calculate it I should change the precision in R, otherwise the result is Inf, and I don't know how to do it.
As Livius points out in his comment, this is an issue with R (and in fact, most programming language), with how numbers are represented in binary.
To work with extremely large/small floating point numbers, you can use the Rmpfr library:
install.packages("Rmpfr")
library("Rmpfr")
x <- c(-2.5e+59, -5.6e+60)
y <- mpfr(x, 6) # the second number is how many precision **bits** you want - NB: not decimal places!
y^6
# 2 'mpfr' numbers of precision 6 bits
# [1] 2.50e356 3.14e364
To work with numbers that are even larger than R can handle (e.g. exp(1800)) you can use the "Brobdingnag" package:
install.packages("Brobdingnag")
library("Brobdingnag")
## An example of a single number too large for R:
10^1000.7
# [1] Inf
## Now using the Brobdingnag package:
10^as.brob(1000.7)
# [1] +exp(2304.2)