Recursion function in R - r

Here is the code, that calculate the binomial coefficient:
binomial_coef <- function(n,r){
if (n == r | r == 0){
return(1)
}
else{
result <- binomial_coef(n-1,r-1) + binomial_coef(n-1,r)
return(result)
}
}
Can you please explain how this code works? How can it calculate, when the function(binomial_coef) isn't define(I mean, there is no formula inside the code)
Thanks

The function(binomial_coef) is indeed defined. This is another way of solving nCr.
nCr= n-1Cr-1 + n-1Cr
So the required nCr gets calculated according to this formula recursively.

Related

How to solve an equation y=ax^2+bx+c when x is unknown and y known

I have this equation:
y = -0.00248793*x^2+20.77173764*x-371.01805798
And I would like to obtain the result of the equation when I give "y" numbers,
edited explanation 2/06/20:
I want to add a vector as my "y", and receive an output of one vector also.
This problem is a biological one, in which I performed citokine bead array (CBA) and I stablished a reference curve which is sinusoidal.
after stablishing the degree of the equation making the following:
fitil6_1=lm(Standards$`IL6 median`~poly(concentration,1,raw=TRUE))
fitil6_2=lm(Standards$`IL6 median`~poly(concentration,2,raw=TRUE))
fitil6_3=lm(Standards$`IL6 median`~poly(concentration,3,raw=TRUE))
fitil6_4=lm(Standards$`IL6 median`~poly(concentration,4,raw=TRUE))
lines(concentration,predict(fitil6_1,data.frame(x=concentration)),col="red")
lines(concentration,predict(fitil6_2,data.frame(x=concentration)),col="green")
lines(concentration,predict(fitil6_3,data.frame(x=concentration)),col="blue")
lines(concentration,predict(fitil6_4,data.frame(x=concentration)),col="purple)
legend(20,40000,legend=c("de grau 1","de grau 2","de grau 3","de grau 4"),lty=1,col=c("red","green","blue","purple"))
I have chosen the degree 2 formula as it fits better to my dots for this cytokine (and most cytokines in this study)
So when I make
coef(fitil6_2)
(Intercept) poly(concentration, 2, raw = TRUE)1 poly(concentration, 2, raw = TRUE)2
-8.262381e+02 2.371377e+01 -2.847135e-03
I receive that output and then I am able to build the formula (in this case):
y=-2.847135e-03 *x^2+2.371377e+01*x-8.262381e+02
but as my independent value is what I know is pretty difficult to isolate x!
(end of the editing)
I have tried many things like making function(x,y) but when you specify this you need to give a number of y, so really I am litlle bit lost!
Thank you
As #Dave2e said, you can solve this particular example by algebra. But you might need a programmatic solution, or you might be using the quadratic as an easy example. in which case...
Rewrite your problem as "what value of y satisfies -0.00248793*x^2+20.77173764*x-371.01805798 - y = 0?".
There are plenty of ways to find the zeroes of a function. That's what you've turned your problem into. Suppose your "known value of y" is 10...
f <- function(x, y) {
-0.00248793*x^2+20.77173764*x-371.01805798 - y
}
answer <- stats::uniroot(f, interval=c(0, 50), y=10)
# Check we've got the right answer
f(answer$root, 10)
Giving
[1] -1.186322e-10
Using this method, you do need to find/guess a range within which the answer might lie. That's the purpose of the interval=c(0.50) part of the call to uniroot. You can read the online help for more information about the value returned by uniroot and things you might want to look out for.
Thank you for all who answered I have just started in this page, this worked for me:
isolating "y" and then making a function with the quadratic formula to x:
delta<-function(y,a,b,c)
{k=(-b+sqrt(b^2-4*a*(c-y)))/(2*a)
print(k)
}
delta(citoquines_valero$`IFNg median`,-1.957128e-03,1.665741e+01,-7.522327e+02)
#I will use that one as a provisional solution.
#I have also been told to use this, but is not working properly:
result <- function(y,a,b,c){
# Constructing delta
delta<-function(y,a,b,c){
b^2-4*a*(c-y)
}
if(delta(a,b,d) > 0){ # first case D>0
x_1 = (-b+sqrt(delta(y,a,b,c)))/(2*a)
x_2 = (-b-sqrt(delta(y,a,b,c)))/(2*a)
if (x_1 >= 0) {
print(x_1)
else if (x_2 >= 0){
print(x_2)
}
}
print(result)
else if(delta(a,b,d) == 0){ # second case D=0
x = -b/(2*a); return(x)
}
else {"There are no real roots."}; # third case D<0```
return("There are no real roots.")
}
}

How to create my own binomial coefficient function in R

I have created a factorial function which is then used to create a function for the binomial coefficient. My factorial function works but the binomial function does not.
I needed to create a factorial function which was then to be used to create a binomial coefficient function using R.
I was not allowed to use the base program's functions such as factorial nor choose.
I had to use for statements, logics etc. even though it is inefficient.
I had to print the factorial of zero and ten, then the binomial coefficient with n = 5, and k = 2
fact <- function(n) {
x <- 1
if(n == 0) {
print(1)
} else {
for(i in 1:n) {
x <- x*i
}
}
print(x)
}
fact(0)
fact(10)
bc <- function(n, k) {
y <- fact(n) / fact(n - k) * fact(k)
print(y)
}
bc(5, 2)
For the factorial function I got the correct answer
But for the binomial function I was way off.
If someone can show me where I have made the mistake I would be most appreciative.
There are quite a few issues here, both relating to basic R coding and coding in general. Let's go through some of them step-by-step:
Your function fact actually does not return anything. All it does at the moment is print values to the console. If you take a look at help("print") it is stated that
‘print’ prints its argument and returns it invisibly (via ‘invisible(x)’).
So in order for fact to actually return a value we can do
fact <- function(n) {
x <- 1
if (n > 0) {
for (i in 1:n) x <- x * i
}
return(x)
}
I have tidied up your code by removing the unnecessary n == 0 check.
Note that there is still room for improvement. For example, there are better ways to calculate the factorial of a number. Secondly, your function currently does not properly deal with negative numbers. Generally, the factorial is only defined for non-negative integers. So you can either change fact to return NA for negative numbers, or -- perhaps more interesting -- generalise the factorial function to the Gamma function to allow for any real (or even complex) number. Either way, I'll leave this up to you.
Similarly your function bc also does not return anything, and instead writes the value of y to the console. Furthermore you need to be careful of brackets to make sure that the terms (n - k)! and k! are in the denominator. Both issues can be fixed by writing
bc <- function(n,k) return(fact(n)/(fact(n - k) * fact(k)))
To confirm, we calculate the coefficient for 5 choose 2:
bc(5, 2)
#10

Exponential distribution in R

I want to simulate some data from an exp(1) distribution but they have to be > 0.5 .so i used a while loop ,but it does not seem to work as i would like to .Thanks in advance for your responses !
x1<-c()
w<-rexp(1)
while (length(x1) < 100) {
if (w > 0.5) {
x1<- w }
else {
w<-rexp(1)
}
}
1) The code in the question has these problems:
we need a new random variable on each iteration but it only generates new random variables if the if condition is FALSE
x1 is repeatedly overwritten rather than extended
although while could be used repeat seems better since having the test at the end is a better fit than the test at the beginning
We can fix this up like this:
x1 <- c()
repeat {
w <- rexp(1)
if (w > 0.5) {
x1 <- c(x1, w)
if (length(x1) == 100) break
}
}
1a) A variation would be the following. Note that an if whose condition is FALSE evaluates to NULL if there is no else leg so if the condition is FALSE on the line marked ## then nothing is concatenated to x1.
x1 <- c()
repeat {
w <- rexp(1)
x1 <- c(x1, if (w > 0.5) w) ##
if (length(x1) == 100) break
}
2) Alternately, this generates 200 exponential random variables keeping only those greater than 0.5. If fewer than 100 are generated then repeat. At the end it takes the first 100 from the last batch generated. We have chosen 200 to be sufficiently large that on most runs only one iteration of the loop will be needed.
repeat {
r <- rexp(200)
r <- r[r > 0.5]
if (length(r) >= 100) break
}
r <- head(r, 100)
Alternative (2) is actually faster than (1) or (1a) because it is more highly vectorized. This is despite it throwing away more exponential random variables than the other solutions.
I would advise against a while (or any other accept/reject) loop; instead use the methods from truncdist:
# Sample 1000 observations from a truncated exponential
library(truncdist);
x <- rtrunc(1000, spec = "exp", a = 0.5);
# Plot
library(ggplot2);
ggplot(data.frame(x = x), aes(x)) + geom_histogram(bins = 50) + xlim(0, 10);
It's also fairly straightforward to implement a sampler using inverse transform sampling to draw samples from a truncated exponential distribution that avoids rejecting samples in a loop. This will be a more efficient method than any accept/reject-based sampling method, and works particularly well in your case, since there exists a closed form of the truncated exponential cdf.
See for example this post for more details.

Use lapply for a recursion (so without a foor loop)

I'd like to solve a recursion function in R, which is defined as
p(t) = 0.5p(t-1) + 0.2p(t-2)
for t = 3,...,100, where the initial values p(1), p(2) are given.
I know that this would be possible to solve using a for loop just like this one here: Using R to solve a recursion function
I'm wondering whether this is also possible using the lapply() function in R? I think it should somehow be possible, but I don't know where to start. I'd appreciate any hint.
Sure you can use recursive function with lapply.
p <- function(t){
if(t == 1){ return(1) } # arbitrary number
if(t == 2){ return(2) } # arbitrary number
return( 0.5*p(t-1) + 0.2*p(t-2) )
}
lapply(3:100, p)
Note that it is a bad idea to use a recursive function for this problem without some sort of memoization, because it will be of exponential complexity.
The following code works in linear time instead:
p_tab <- c(1, 2, rep(-1, 98)) # 1 and 2 arbitrary numbers
p <- function(t){
if(p_tab[t] != -1) return(p_tab[t])
p_tab[t] <<- 0.5*p_tab[t-1] + 0.2*p_tab[t-2]
}
p_tab <- unlist(lapply( 1:100, p))
p_tab will be filled with the numbers you need. p_tab[100] will be p(100) for instance, if that's the one you need.

Function that returns a mixture of probability densities

In R, I would like to create a function which does the following:
given vectors of means, variances and weights
create a function which is a mixture of normal distributions
return this function
A mixture of normal densities is the sum
f(x) = c_1 * N(mu_1,var_1) + ... + c_n * N(mu_n,var_n).
What's an easy way of doing this in R?
edit
I figured out a very straightforward, perhaps naive way of doing this:
gmix <- function(means,vars,weights){
n <- length(means)
f<- function(t) {
res <- 0;
for(i in 1:n) {
res <- res + weights[i]*dnorm(t,mean=means[i],sd=sqrt(vars[i]))
}
return(res)
}
return(f)
}
I'm no programmer so this might be not a smart way of doing this... If anyone knows a better implementation I'd be glad to hear it.

Resources