so I have an error...
f <- function(x){return(1)}
curve(f(x),0,100,xname="x")
Error in curve(f(x), 0, 100, xname = "x") :
'expr' did not evaluate to an object of length 'n'
Which is strange considering that
F <- function(x){return(0*x+1)}
curve(F(x),0,100,xname="x")
Works just fine... This informed me to think about how R treats data.frame()s.
a <- data.frame(1,2,3)
f(a)
# [1] 1
F(a)
# X1 X2 X3
# 1 1 1 1
Meaning that the Function Vectorize() will fix my problem.
Irregardless this is an acute example of the implicit decisions That R makes, which result in inconsistent behavior.
The problem is the function should return a vector of the same length as a parameter. In your case instead of n, the function always returns a vector of just one. The solution could be
f <- function(x){return(rep(1,length(x)))}
Related
I am trying to calculate the following ( the image says f(n) = n \sum_{i=1}^{\infty} (c(i)*(1-c(i))^n)):
where c(i) is
c <- function(i){1/i^3}
In other words, f(2) is 2*{1^(-3)(1-1^(-3))^2+2^(-3)(1-2^(-3))^2+3^(-3)(1-3^(-3))^2+4^(-3)(1-4^(-3))^2+...}.
How to write such an f function in R?
My initial attempt is:
f <- function(n){n*sum(c*(1-c)^n)}
but this is obviously wrong with error
Error in 1 - c : non-numeric argument to binary operator
Please let me know if further clarification is needed. Thanks.
Clearly, you can't get an infinite sum unless you tackle it analytically, but since we can see that it's a convergent sum, we could look at, say, the first million like this:
f <- function(n) {
C <- 1 / seq(1e6)^3
n * sum(C * (1 - C)^n)
}
Which allows:
f(1)
#> [1] 0.1847138
f(2)
#> [1] 0.3387583
f(3)
#> [1] 0.4674204
In case you are worried that this is not accurate enough, we get the same result out to 7 digits by summing only the first 10,000 terms, so 1 million should be very close to the converged value.
I want to create a function that transforms its object.
I have tried to transform the variable as you would normally, but within the function.
This works:
vec <- c(1, 2, 3, 3)
vec <- (-1*vec)+1+max(vec, na.rm = T)
[1] 3 2 1 1
This doesn't work:
vec <- c(1, 2, 3, 3)
func <- function(x){
x <- (-1*x)+1+max(x, na.rm = T))
}
func(vec)
vec
[1] 1 2 3 3
R is functional so normally one returns the output. If you want to change
the value of the input variable to take on the output value then it is normally done by the caller, not within the function. Using func from the question it would normally be done like this:
vec <- func(vec)
Furthermore, while you can overwrite variables it is, in general, not a good
idea. It makes debugging difficult. Is the current value of vec the
input or output and if it is the output what is the value of the input? We
don't know since we have overwritten it.
func_ovewrite
That said if you really want to do this despite the comments above then:
# works but not recommended
func_overwrite <- function(x) eval.parent(substitute({
x <- (-1*x)+1+max(x, na.rm = TRUE)
}))
# test
v <- c(1, 2, 3, 3)
func_overwrite(v)
v
## [1] 3 2 1 1
Replacement functions
Despite R's functional nature it actually does provide one facility for overwriting although the function in the question is not really a good candidate for it so let us change the example to provide a function incr which increments the input variable by a given value. That is, it does this:
x <- x + b
We can write this in R as:
`incr<-` <- function(x, value) x + value
# test
xx <- 3
incr(xx) <- 10
xx
## [1] 13
T vs. TRUE
One other comment. Do not use T for true. Always write it out. TRUE is a reserved name in R but T is a valid variable name so it can lead to hard to find errors such as when someone uses T for temperature.
Currently, I have
extract_modulo = function(x, n, fn=`[`) fn(x, (n-1L) %% length(x) + 1L)
`%[mod%` = function (x, n) extract_modulo(x, n)
And then:
seq(12) %[mod% 14
#[1] 2
Is this already built into R somewhere? I would think so, because R has several functions that recycle values (e.g., paste). However, I'm not finding anything with help('[['), ??index, or ??mod. I would think an R notation for this would be something like seq(12)[/14/] or as.list(seq(12))[[/14/]], for example.
rep_len() is a fast .Internal function, and appropriate for this use or when recycling arguments in your own function. For this particular case, where you're looking for the value at an index position beyond the length of a vector, rep_len(x, n)[n] will always do what you're looking for, for any nonnegative whole number 'n', and any non NULL x.
rep_len(seq(12), 14)[14]
# [1] 2
rep_len(letters, 125)[125]
# [1] "u"
And if it turns out you didn't need to recycle x, it works just as fine with an n value that is less than length(x)
rep_len(seq(12), 5)[5]
# [1] 5
rep_len(seq(12), 0)[0]
# integer(0)
# as would be expected, there is nothing there
You could of course create a wrapper if you'd like:
recycle_index <- function(x, n) rep_len(x, n)[n]
recycle_index(seq(12), 14)
# [1] 2
I'm not very familiar with the optim function, and I wanted to get these informations from its results: a) how many iterations were needed for achieving the result? and b) to plot the sequence of partial solutions, that is, the solution obtained in the end of each iteration.
My code until now looks like this:
f1 <- function(x) {
x1 <- x[1]
x2 <- x[2]
x1^2 + 3*x2^2
}
res <- optim(c(1,1), f1, method="CG")
How can I improve it to get further information?
Thanks in advance
You could modify your function to store the values that are passed into it into a global list.
i <- 0
vals <- list()
f1 <- function(x) {
i <<- i+1
vals[[i]] <<- x
x1 <- x[1]
x2 <- x[2]
x1^2 + 3*x2^2
}
res <- optim(c(1,1), f1, method="CG")
Now if you examine i and vals after you run the function you can see what happened. If you want to see the values while optim is running throw a print statement into the function as well.
Passing trace=1 as a control parameter to optim gives you more detailed information about the progress of the optimization:
res <- optim(c(1,1), f1, method="CG", control=list(trace=1))
# Conjugate gradients function minimizer
# Method: Fletcher Reeves
# tolerance used in gradient test=3.63798e-12
# 0 1 4.000000
# parameters 1.00000 1.00000
# * i> 1 4 0.480000
# parameters 0.60000 -0.20000
# i> 2 6 0.031667
# ......
# * i> 13 34 0.000000
# parameters -0.00000 0.00000
# 14 34 0.000000
# parameters -0.00000 0.00000
# Exiting from conjugate gradients minimizer
# 34 function evaluations used
# 15 gradient evaluations used
However, it seems like the information is only written to standard output, so you will have to use sink to pipe the output to a text file, and then do some editing to get the parameter values for plotting.
If all you wanted was the number of function evaluations, see the $counts element of the result:
counts: A two-element integer vector giving the number of calls to
‘fn’ and ‘gr’ respectively. This excludes those calls needed
to compute the Hessian, if requested, and any calls to ‘fn’
to compute a finite-difference approximation to the gradient.
For the partial solutions you'll need #Dason's solution or something like it.
Let me describe the problem setting. The function I am depicting is a probability function and upon integration it's value would have to be equal to 1. So I will be dividing the result of the integration by 1 to give the value of C. So I can't assign value to C.
Have a look at the below code and error message -
> f <- function(x) (C*x*(exp(-x)))
> z=integrate(f, lower = 0, upper=Inf)
Error in C * x : non-numeric argument to binary operator
How am I supposed to define C here ?
Second Question- Can somebody figure what's wrong with value of z?
> f <- function(x) (x*(exp(-x)))
> z=integrate(f, lower = 0, upper=Inf)
> z
1 with absolute error < 6.4e-06
> 1/z
Error in 1/z : non-numeric argument to binary operator
Make C = 1 for when you compute the integral of the function. For that, you can make it an optional argument to your function with a default value:
f <- function(x, C = 1) C * x * exp(-x)
Then, compute:
z <- integrate(f, lower = 0, upper = Inf)
For the integral to be 1 with the real value for C, you need C * z == 1, i.e.:
C <- 1 / z$value
C
# [1] 1
As it turns out, the integral z is already equal to 1 so picking C = 1 was a lucky choice. You have nothing to do and you can just start using f as-is. Had it not been the case, I would have suggested to redefine f:
f_final <- function(x) f(x, C = 1 / z$value)
(Regarding your second question, you just had to look at the documentation for ?integrate and refer to the "Value" section.)