Manually written function doesn't behave the same as the gamma function - r

So I implemented a function that calculates the value of the gamma function. and when I try to multiply f5(a) with a numeric I receive the error : Error in result * f5(a) : non-numeric argument to binary operator and if I instead use result * gamma(a) which is the predefined function it works just fine. It seems like it won't let me do any arithmetic operation with f5 even though it returns the same result as gamma
f5 <- function(a)
{
f <- function(x)
x^(a-1)*exp(-x)
integrate(f, 0, Inf)
}
f6 <- function(a)
{
if (a < 0)
print("a is negative")
else if (a%%1 == 0)
return (factorial(a-1))
else
{
result <- 1
while (a > 1)
{
result <- result * (a - 1)
a <- a - 1
}
result <- result * f5(a)
result
}
}
gamma(0.3)
f5(0.3)
f6(0.3)

This is because of the class of object that gets returned from f5().
class(f5(0.3))
[1] "integrate"
This is a named list object, and you can call the specific value from it:
names(f5(a))
[1] "value" "abs.error" "subdivisions" "message" "call"
You want the value component. Modifying f6() to the code below makes it work:
f6 <- function(a){
if (a < 0){
print("a is negative")
}else if (a%%1 == 0){
return (factorial(a-1))
}else{
result <- 1
while (a > 1){
result <- result * (a - 1)
a <- a - 1
}
result <- result * f5(a)$value
result
}
}

Related

replacement has length zero in fibonacci sequence in R code

So I have this code for the fibonacci sequence, and I keep getting an error when I try to print out the value of the function.
fibonacci <- function(nn) {
if (!(nn%%1==0) | (nn<1)){
return(0)
}
my.fib <- c(1,1)
for (kk in 3:nn){
my.fib[kk] <- my.fib[kk-1] + my.fib[kk-2]
}
return(my.fib[nn])
}
fibonacci(7)
fibonacci(5)
fibonacci(1)
fibonacci(1.5)
fibonacci(0)
It prints everything correctly for 7,5,1.5 and 0, as it gives me the vaules 13, 5, 0, and 0. But when trying to print fibonacci(1), I get the error
Error in my.fib[kk] <- my.fib[kk - 1] + my.fib[kk - 2] :
replacement has length zero
I want to leave as much as the code the same as possible.
Add another if condition to check for nn = 1.
fibonacci <- function(nn) {
if (!(nn%%1==0) | (nn<1)){
return(0)
} else if(nn == 1) return(1)
my.fib <- c(1,1)
for (kk in 3:nn){
my.fib[kk] <- my.fib[kk-1] + my.fib[kk-2]
}
return(my.fib[nn])
}

Translating a VBA function into R

I am attempting to translate the function DISCRINV() which is an excel function available in the simtools excel add-in that was created by Roger Myerson into an R function. I believe i am close, but am having difficulty understanding the looping syntax of VBA.
The VBA code for this function is as follows:
Function DISCRINV(ByVal randprob As Double, values As Object, probabilities As Object)
On Error GoTo 63
Dim i As Integer, cumv As Double, cel As Object
If values.Count <> probabilities.Count Then GoTo 63
For Each cel In probabilities
i = i + 1
cumv = cumv + cel.Value
If randprob < cumv Then
DISCRINV = values.Cells(i).Value
Exit Function
End If
Next cel
If randprob < cumv + 0.001 Then
DISCRINV = values.Cells(i).Value
Exit Function
End If
63 DISCRINV = CVErr(xlErrValue)
End Function
Attempting to translate this directly from the VBA code i have come up with this (Not Correct):
DISCRINV <- function(R,V,P){
if(length(V) != length(P)){
print("ERROR NUMBER OF VALUES DOES NOT EQUAL NUMBER OF PROBABILITIES")
} else{
for (i in 1:length(P)){
cumv=cumv+P[i]
if (R < cumv){
DISCY1 = V[i]
return(DISCY1)
}
print(cumv)
if (R < cumv +0.001){
DISCY2 = V[i]
return(DISCY2)
}
}
}
}
Attempting to translate this through my understanding of what it is doing i have come up with this:
DISCRINV <- function(x,values,probabilities){
require(FSA)
precumsum <- pcumsum(probabilities)
middle <- c()
for (i in 1:(length(values)-2)){
if (precumsum[i+1] <= x & x < precumsum[i+2]){
middle[i] <- values[i+1]}
else{
middle[i] <- 0
}
}
firstrow <- ifelse(x < precumsum[2], values[1], 0)
lastrow <- ifelse(precumsum[length(precumsum)] <= x , values[length(precumsum)] , 0)
Gvector <- c(firstrow,middle,lastrow)
print(firstrow)
print(middle)
print(lastrow)
print(Gvector)
simulatedvalue <- sum(Gvector)
return(simulatedvalue)
}
The latter option works 99% of the time, but not when the first function parameter is over 0.5, the second parameter is a vector of values c(1000,2000) and the third parameter is a vector (0.5,0.5). The case of the latter option not working 100% of the time is what has led me to try to translate the function directly. Could someone please give some insight into where my translation is going wrong?
Additionally a description of the function is as follows:
DISCRINV(randprob, values, probabilities) returns inverse cumulative values for a discrete random variable. When the first parameter is a RAND, DISCRINV returns a discrete random variable with possible values and corresponding probabilities in the given ranges.
Thank you in advance for the insight!
For anyone that is interested, i was able to successfully translate this VBA script using this code
DISCRINV <- function(x,values,probabilities){
require(FSA)
precumsum <- pcumsum(probabilities)
middle <- c()
if(length(values <3 )){
if(x<0.5){
middle1 <- values[1]
return(middle1)
} else{
middle2 <- values[2]
return(middle2)
}
}
else{
for (i in 1:(length(values)-2)){
if (precumsum[i+1] <= x & x < precumsum[i+2]){
middle[i] <- values[i+1]}
else{
middle[i] <- 0
}
}
firstrow <- ifelse(x < precumsum[2], values[1], 0)
lastrow <- ifelse(precumsum[length(precumsum)] <= x , values[length(precumsum)] , 0)
Gvector <- c(firstrow,middle,lastrow)
print(firstrow)
print(middle)
print(lastrow)
print(Gvector)
simulatedvalue <- sum(Gvector)
return(simulatedvalue)
}
}

Error in if (num < 0) { : missing value where TRUE/FALSE needed

y <- as.integer(readline(prompt ="Enter a number: "))
factorial = 1
if (y< 0){
print("Error")
} else if (y== 0)
{
print("1")
} else
{
for(i in 1:y) {
factorial = factorial * i
}
return(factorial)
}
wondering why this is giving:
Error in if (y< 0) { : missing value where TRUE/FALSE needed
is it cause the first line has data type NA_integer?
There are three possible ways to pass values to the if statement.
y <- 1
if (y > 0) print("more")
This one works as expected.
y <- 1:3
if (y > 0) print("ignores all but 1st element")
As the warning message will tell you, only the first element was used to evaluate it. You could use any or all to make this right.
y <- NA
if (y > 0) print("your error")
This case actually gives you your error. I would wager a bet that y is somehow NA. You will probably need to provide a reproducible example (with data and the whole shebang) if you'll want more assistance. Note also that it helps visually structure your code to improve readability.

In if (wspolczynnik > waga_linkow[n]) { : the condition has length > 1 and only the first element will be used

I have two arrays:
wspolczynnik
and
waga_linkow
and I would like to enter the following instruction:
if (wspolczynnik > waga_linkow[n]){
print('jest ok ')
} else {
print('za male')
}
I get the following warning message:
[1] "za male"
Warning message:
In if (wspolczynnik > waga_linkow[n]) { :
the condition has length > 1 and only the first element will be used
How can I correct the instruction?
Your code is using the whole first vector, you need to add the [n] after both vectors in the if argument, for example:
A <- c(1,2,3,4)
B <- c(0,0,1,5)
n <- 1
if (A[n] == B[n]){
print('A equal to B')
} else {
print('A not equal to B')
}
You could return results for all entries of the two vectors (I.e. A[1] and B[1], A[2] and B[2]...) writing a function and using a for loop
print_func <- function(a, b){
if(a == b){
print('a equal to b')
}
if (a != b){
print('a not equal to b')
}
}
for(i in 1:4){
print_func(A[i], B[i])
}
However, my personal preference is to make a vectorised version.
A <- c(1,2,3,4)
B <- c(0,0,1,4)
R <- rep("Not Equal", 4)
R[A == B] <- "Equal"
R

Why does "Sum()" succeed where "+" fails in recursive R function?

I am experimenting with the functional programming paradigm in R. I have defined a function that sums a sequence of integers from n to m. When I use sum() the function returns the expected result:
sumRange <- function(n, m) {
if (n <= m) {
return(sum(n, sumRange((n + 1), m)))
}
}
sumRange(1, 10)
# [1] 55
However, when I use the + operator the function returns numeric(0):
sumRange <- function(n, m) {
if (n <= m) {
return(n + sumRange((n + 1), m))
}
}
sumRange(1, 10)
# numeric(0)
Why does the operator + not work in this recursive function? Is there a way to rewrite the function so that it does?
The issue is that you never specify an else condition, hence at the end of the recursion it appears that R is returning NULL when the if condition fails. Returning 0 as the else condition fixes your problem:
sumRange <- function(n, m) return(ifelse (n <= m, (n + sumRange((n+1), m)), 0))
sumRange(1, 10)
[1] 55
Note that this is essentially defining a base case for your recursion. A base case, when hit, ends the recursion and causes the calls on the stack to be unwound.
To see the issue with the way you phrased your code, try writing out your function explicitly:
sumRange <- function(n, m) {
if (n <= m) {
return(n + sumRange((n+1), m))
}
// but what gets returned if n > m ?
// this is undefined behavior
}
I'm not an R guru, but my understanding is that R was written in C, and C might allow a recursion like this with no else condition. But the behavior is not well defined and you should not be relying on it.
Demo
If there is no return (using a explicit or implicit return statement) is executed, then R functions seems to return a NULL object.
If you add numerical value to a this object, it will simply return numeric(0).
So, what happens in the second case is that when n reaches 11, it returns a NULL object, and goes back adding values to it. But NULL + 10 + 9 .. = numeric(0).
Check this with
no_ret <- function ()
{
# just return nothing
}
obj <- no_ret()
obj
# NULL
class(obj)
# "NULL
new_obj <- obj + 10
new_obj
# numeric(0)
When the first function is executed, the what the sum statement get is
a vector with a NULL in it. For example,
vec <- c(NULL, 10, 9,...) which is actually vec <- c(10, 9, ...), so you get the expected outcome.
> c(NULL, 10:1)
[1] 10 9 8 7 6 5 4 3 2 1
> sum(NULL, 10:1)
[1] 55
> NULL + 10:1
integer(0)

Resources