No sign change found error in R but not excel - r

Just trying to understand why when I find the root of the following equation in excel I get a value however in R I get the "no sign change found error"
(-exp(-i*x))-x + 1
i = 1 in this case.
I'm plotting a graph where the value for i is 1:5. I've done this manually on excel and got a value of 0.003 when i = 1, here is the graph for all values of i: image 1
When try to find the root for when i = 1 in R though I get the error.
This is the code I am using to find the root:
func1 <- function(x) {
(-exp(-1*x))-x+1
}
root <- uniroot(func1, lower =0.5, upper = 1, extendInt = "yes")
print(root)
print(root$root)
}
Plotting the equation when i = 1 gives the following curve: image 2
Looking at the curve it doesn't seem like f(x) crosses 0 which explains the error, however, I get a value in excel.
Any help on this would be really appreciated
Thanks

This is the best I can offer. It is using a method of derivatives I found at http://rpubs.com/wkmor1/simple-derivatives-in-r. It will allow you to get the roots from newtons method.
options(scipen = 999)
f<-function(x) (-exp(-x)-x+1)
g<-function(x) { }
body(g)<-D(body(f),"x")
x <- 19
y<-vector()
y[1]<-x
for(i in 2:500) {
y<-c(y, y[i-1] - (f(y[i-1])/g(y[i-1])))
if(y[i]==y[i-1]) break
}
y
The output looks like this:
> y
[1] 19.000000000000000 0.999999893546867 0.418023257075328 0.194491909332762
[5] 0.094095681658666 0.046310116577025 0.022976345768161 0.011444180565743
[9] 0.005711176200954 0.002852869974152 0.001425756748278 0.000712708975595
[13] 0.000356312158327 0.000178145499021 0.000089070105497 0.000044534390909
[17] 0.000022267031356 0.000011133470771 0.000005566723944 0.000002783342584
[21] 0.000001391644148 0.000000695821730 0.000000347990248 0.000000173795172
[25] 0.000000086916841 0.000000043487300 0.000000023063442 0.000000013435885
[29] -0.000000003090351 -0.000000003090351
I hope this helps.

Related

Optimization function gives incorrect results for 2 similar data sets

I have 2 datasets not very different to each other. Each dataset has 27 rows of actual and forecast values. When tested against Solver in Excel for minimization of the absolute error (abs(actual - par * forecast) they both give nearly equal values for the parameter 'par'. However, when each of these data sets are passed on to the same optimization function that I have written, it only works for one of them. For the other data set, the objective always gets evaluated to zero (0) with'par' assisgned the upper bound value.
This is definitely incorrect. What I am not able to understand is why is R doing so?
Here are the 2 data sets :-
test
dateperiod,usage,fittedlevelusage
2019-04-13,16187.24,17257.02
2019-04-14,16410.18,17347.49
2019-04-15,18453.52,17246.88
2019-04-16,18113.1,17929.24
2019-04-17,17712.54,17476.67
2019-04-18,15098.13,17266.89
2019-04-19,13026.76,15298.11
2019-04-20,13689.49,13728.9
2019-04-21,11907.81,14122.88
2019-04-22,13078.29,13291.25
2019-04-23,15823.23,14465.34
2019-04-24,14602.43,15690.12
2019-04-25,12628.7,13806.44
2019-04-26,15064.37,12247.59
2019-04-27,17163.32,16335.43
2019-04-28,17277.18,16967.72
2019-04-29,20093.13,17418.99
2019-04-30,18820.68,18978.9
2019-05-01,18799.63,17610.66
2019-05-02,17783.24,17000.12
2019-05-03,17965.56,17818.84
2019-05-04,16891.25,18002.03
2019-05-05,18665.49,18298.02
2019-05-06,21043.86,19157.41
2019-05-07,22188.93,21092.36
2019-05-08,22358.08,21232.56
2019-05-09,22797.46,22229.69
Optimization result from R
$minimum
[1] 1.018188
$objective
[1] 28031.49
test1
dateperiod,Usage,fittedlevelusage
2019-04-13,16187.24,17248.29
2019-04-14,16410.18,17337.86
2019-04-15,18453.52,17196.25
2019-04-16,18113.10,17896.74
2019-04-17,17712.54,17464.45
2019-04-18,15098.13,17285.82
2019-04-19,13026.76,15277.10
2019-04-20,13689.49,13733.90
2019-04-21,11907.81,14152.27
2019-04-22,13078.29,13337.53
2019-04-23,15823.23,14512.41
2019-04-24,14602.43,15688.68
2019-04-25,12628.70,13808.58
2019-04-26,15064.37,12244.91
2019-04-27,17163.32,16304.28
2019-04-28,17277.18,16956.91
2019-04-29,20093.13,17441.80
2019-04-30,18820.68,18928.29
2019-05-01,18794.10,17573.40
2019-05-02,17779.00,16969.20
2019-05-03,17960.16,17764.47
2019-05-04,16884.77,17952.23
2019-05-05,18658.16,18313.66
2019-05-06,21036.49,19149.12
2019-05-07,22182.11,21103.37
2019-05-08,22335.57,21196.23
2019-05-09,22797.46,22180.51
Optimization result from R
$minimum
[1] 1.499934
$objective
[1] 0
The optimization function used is shown below :-
optfn <- function(x)
{act <- x$usage
fcst <- x$fittedlevelusage
fn <- function(par)
{sum(abs(act - (fcst * par)))
}
adjfac <- optimize(fn, c(0.5, 1.5))
return(adjfac)
}
adjfacresults <- optfn(test)
adjfacresults <- optfn(test1)
Optimization result from R
adjfacresults <- optfn(test)
$minimum
[1] 1.018188
$objective
[1] 28031.49
Optimization result from R
adjfacresults <- optfn(test1)
$minimum [1]
1.499934
$objective
[1] 0
Can anyone help to identify why is R not doing the same process over the 2 data sets and outputting the correct results in both the cases.
The corresponding results using Excel Solver for the 2 datasets are as follows :-
For 'test' data set
par value = 1.018236659
objective function valule (min) : 28031
For 'test1' data set
par value = 1.01881062927878
objective function valule (min) : 28010
Best regards
Deepak
That's because the second column of test1 is named Usage, not usage. Therefore, act = x$usage is NULL, and the function fn returns sum(abs(NULL - something)) = sum(NULL) = 0. You have to rename this column to usage.

Using for loop variable to access element in array yielding NA in R

I'm using a nested for loop to create a greedy algorithm in R.
z = 0
for (j in 1:length(t))
for (i in 1:(length(t) - j))
if ((t[j + i] - t[j]) >= 30)
{z <- c(z,j + i - 1)
j <- j + i - 1
break}
z
Where t is a vector such as:
[1] 12.01485 26.94091 33.32458 49.46742 65.07425 76.05700
[7] 87.11043 100.64116 111.72977 125.72649 139.46460 153.67292
[13] 171.46393 184.54244 201.20850 214.05093 224.16196 237.12485
[19] 251.51753 258.45865 273.95466 285.42704 299.01869 312.35587
[25] 326.26289 339.78724 353.81854 363.15847 378.89307 390.66134
[31] 402.22007 412.86049 424.23181 438.50462 448.88005 462.59917
[37] 473.65289 487.20678 499.80053 509.14141 526.03873 540.17209
[43] 550.69941 565.74602 576.06882 589.07297 598.53208 614.20677
[49] 627.44605 648.08346 665.49614 681.46445 691.01806 704.05762
[55] 714.09172 732.04124 745.90960 758.52628 769.80519 779.41537
[61] 788.35732 805.78547 818.75262 832.71196 844.97859 856.08608
[67] 865.72998 875.55945 887.20862 900.00000
The goal for the function is to find the indexes whose differences are as close to 30 as possible and save them in z.
For example, with the vector t provided, I would expect z to be [0, 2, 4, 6, 8, 10,...70]
The functionality is not my concern right now, as I am running into the error:
Error in if ((t[j + i] - t[j]) >= 30) { :
missing value where TRUE/FALSE needed
I'm new to R so I know I'm not utilizing the vectorization that R is known for. I simply want to have 'j' and 'i' as "counter variables" that I can use to access specific elements of vector t, but for a reason unknown to me, the if statement is not yielding a T/F value.
Any suggestions?
I know you want to learn how to use for-loop, but it is difficult to help you because you did not provide a reproducible example. On the other hand, in R a lot of functions were vectorized, meaning that you can avoid for-loop to achieve the same task with more efficient ways.
Based on the description in your post "The goal for the function is to find the indexes whose differences are as close to 30 as possible and save them in z." I provided the following example to address your question without a for-loop.
z <- which.min(abs(diff(vec) - 30))
z
# [1] 49
vec[c(z, z + 1)]
# [1] 627.4461 648.0835
Based on the data you provided, the indices with the numbers difference which are the closest to 30 is 49. The numbers are 627.4461 and 648.0835.
Data
vec <- c("12.01485 26.94091 33.32458 49.46742 65.07425 76.05700 87.11043
100.64116 111.72977 125.72649 139.46460 153.67292 171.46393
184.54244 201.20850 214.05093 224.16196 237.12485 251.51753
258.45865 273.95466 285.42704 299.01869 312.35587 326.26289
339.78724 353.81854 363.15847 378.89307 390.66134 402.22007
412.86049 424.23181 438.50462 448.88005 462.59917 473.65289
487.20678 499.80053 509.14141 526.03873 540.17209 550.69941
565.74602 576.06882 589.07297 598.53208 614.20677 627.44605
648.08346 665.49614 681.46445 691.01806 704.05762 714.09172
732.04124 745.90960 758.52628 769.80519 779.41537 788.35732
805.78547 818.75262 832.71196 844.97859 856.08608 865.72998
875.55945 887.20862 900.00000")
vec <- strsplit(vec, split = " ")[[1]]
vec <- as.numeric(grep("[0-9]+\\.[0-9]+", vec, value = TRUE))

Using for loops to save a matrix of data?

I am trying to find the probability density functions of a wind data. Below is how I calculate the scale parameter from the mean wind speeds.
k<-2
for(i in 1:length(Windmean)){
Scale[i]=as.numeric(Windmean[i]/(exp(gammaln(1+(1/k)))))
}
> Scale
[1] 3.913934 3.996000 4.012884 3.925220 3.856707 3.849608 3.820578 3.943110 3.945975 3.842338 3.891791
[12] 3.933083 3.993944 3.907775 3.847120 3.853263 3.917156 4.028956 3.878879 3.753880 3.969074 3.818923
[23] 3.855913 3.993075 3.985828 3.914240 3.854336 3.620460 3.848180 3.843788 3.830617 3.841890 3.879547
[34] 3.904059
If these are my results for scale parameter I want to use the formula below to get the wind probability Wind_prob. I do.
Scale<- cbind(3.913934,3.996000,4.012884,3.925220,3.856707,3.849608,
3.820578,3.943110,3.945975,3.842338,3.891791,3.933083,3.993944,3.907775,
3.847120,3.853263,3.917156,4.028956,3.878879,3.753880,3.969074,3.818923,
3.855913,3.993075,3.985828,3.914240,3.854336,3.620460,3.848180,3.843788,
3.830617,3.841890,3.879547,3.904059) ##Length 34
bins<-cbind(seq(0.5,25,by=0.5)) ##Length 51
bins<-cbind(bins)
shape<-k
for(i in 1:length(bins)){
for(o in 1:length(Scale)){
Wind_prob[i]<-(0.5*(exp(-1*(bins[i,1]/shape)^shape))*(shape/as.numeric(Scale[o]))*((bins[i,1]/as.numeric(Scale[o]))^(shape-1)))
}
}
I am getting a list of 51 probability functions (i=34) but I should get a matrix of [51*34]. Basically, I want to get 51 probability functions for each 34 scale functions. It seems my iterations are not been saved at matrix. I tried as.matrix, as.array as well in the wind_prob but couldn't get it working. Would anyone be kind to point out the changes I need to make in the code? Thanks.
You need to use a matrix:
Scale <- c(3.913934,3.996000,4.012884,3.925220,3.856707,3.849608,
3.820578,3.943110,3.945975,3.842338,3.891791,3.933083,3.993944,3.907775,
3.847120,3.853263,3.917156,4.028956,3.878879,3.753880,3.969074,3.818923,
3.855913,3.993075,3.985828,3.914240,3.854336,3.620460,3.848180,3.843788,
3.830617,3.841890,3.879547,3.904059) ##Length 34
bins <- seq(0.5, 25, by = 0.5) # length 50
shape <- 2
Wind_prob <- matrix(NA_real_, length(bins), length(Scale))
for (j in seq_along(Scale)) {
for (i in seq_along(bins)) {
Wind_prob[i, j]<-(0.5*(exp(-1*(bins[i]/shape)^shape))*
(shape/as.numeric(Scale[j]))*
((bins[i]/as.numeric(Scale[j]))^(shape-1)))
}
}

Calculate Taylor series using rSymPy

I have been trying out the R interface rSymPy to the CAS SymPy and it works quite well. However, I cannot find the correct syntax for using some of the more complex features, such as finding a Taylor series.
For example, I have tried the following:
library(rSymPy)
sympy("var('p')")
#
##### Cannot make this work ???
#
sympy("from sympy.mpmath import *")
xt <- sympy("p=taylor(exp, 0, 10)")
But it throws the error:
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
SyntaxError: ("no viable alternative at input '='", ('<string>', 1, 8, '__Rsympy= from sympy.mpmath import *\n'))
Any help appreciated.
There does not appear to be an explicit Taylor series available, but the series function is available. The following code works:
library(rSymPy)
sympy("var('p')")
sympy("var('x')") # or sympy("x = Symbol('x', real=True)")
#
xt <- sympy("p=series(exp(x), x, 0, 10)") # expand about 0 to 10th order
which gives the answer:
[1] "1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + x**6/720 + x**7/5040 + x**8/40320 + x**9/362880 + O(x**10)"
We can check this answer by modifying the code to:
library(rSymPy)
sympy("var('p')")
sympy("var('x')") # or sympy("x = Symbol('x', real=True)")
#
xt <- sympy("p=series(exp(x), x, 0, 10)") # expand about 0 to 10th order
# Remove order information
xt0 <- sympy("p.removeO()")
# Test results
x <- 1/3
T1 <- eval(parse(text=xt0)) # Evaluate the result, xt0
T2 <- exp(x) # The correct value
print(T1-T2) # Print the error
Finally, the error from the series expansion is:
[1] -4.811929e-12
I hope this is helpful to anyone else wishing to use the R package rSymPy

Solve simple equation in R

I have a probably really basic question concerning the possibility to solve functions in R, but to know the answer would really help to understand R better.
I have following equation:
0=-100/(1+r)+(100-50)/(1+r)^2+(100-50)/(1+r)^3+...(100-50)/(1+r)^10
How can I solve this equation in R finding the variable r?
I tried sth. like this:
n <- c(2:10)
0 = -100/(r+1)+sum((100-50)/((1+r)^n))
But got an error message:
Error in 0 = -100/(r + 1) + sum((100 - 50)/((1 + r)^n)) :
invalid (do_set) left-hand side to assignment
What's the problem and how can I find r?
There are plenty of optimization and root finding libraries for R link here. But in native R:
fnToFindRoot = function(r) {
n <- c(2:10)
return(abs(-100/(r+1)+sum((100-50)/((1+r)^n))))
}
# arbitrary starting values
r0 = 0
# minimise the function to get the parameter estimates
rootSearch = optim(r0, fnToFindRoot,method = 'BFGS', hessian=TRUE)
str(rootSearch)
fnToFindRoot(rootSearch$par)
That function is very volatile. If you are willing to bracket the root, you are probably better off with uniroot:
fnToFindRoot = function(r,a) {
n <- c(2:10)
return((-100/(r+1)+sum((100-50)/((1+r)^n)))-a)
}
str(xmin <- uniroot(fnToFindRoot, c(-1E6, 1E6), tol = 0.0001, a = 0))
The a argument is there so you can look for a root to any arbitrary value.
Try bisection. This converges to r = 0.4858343 in 25 iterations:
library(pracma)
bisect(function(r) -100/(1+r) + sum(50/(r+1)^seq(2, 10)), 0, 1)
giving:
$root
[1] 0.4858343
$f.root
[1] 8.377009e-07
$iter
[1] 25
$estim.prec
[1] 1.490116e-08
Let x = 1/(1+r), so your equation should be:
0-100x + 50x^2 + 50x^3 + ... + 50x^10 = 0.
then in R:
x <- polyroot(c(0, -100, rep(50, 9)))
(r <- 1/x - 1)
Here is the answer:
[1] Inf+ NaNi 0.4858344-0.0000000i -1.7964189-0.2778635i
[4] -0.3397136+0.6409961i -0.3397136-0.6409961i -1.4553556-0.7216708i
[7] -0.9014291+0.8702213i -0.9014291-0.8702213i -1.7964189+0.2778635i
[10] -1.4553556+0.7216708i

Resources