简体   繁体   中英

apply an optimal function to a function using a for loop in r

I wrote a simple function for maximum likelihood and would like this function to give different result based on the different values of its parameters using for loop in R. That is my function include an expression based on for loop. My function works well and the result are saved in a list. Then, Since I have two different results, I would like to apply the optim function to my function based on each part of my function. For example,

ff <- function(x,mu=c(2,0.5),sd=c(0.2,0.3)){
  out <- vector("list",2)
  for (i in 1:2){
    out[[i]] <- -sum(log(dnorm(x,mu[[i]],sd[[i]]))) ## here I have two different part of my funcitons wrap as one using for loop.
  }
return(out)
}


 set.seed(123)
    x <- rnorm(10,2,0.5)
    x

Then the result of my function is:

> ff(x)
[[1]]
[1] 25.33975

[[2]]
[1] 101.4637

Then, since my function has two different parts wrap as one using for loop, I would like to apply the optim function to this function based on each part of it. I tried many own methods and they did not work. Here is one of my tries:

op <- vector("list",2)
for(i in 1:2){

op <- optim(c(0.5,0.5),fn=ff[[i]],i=i)
}

That is, I want the optim function to evaluate my function at the first value of my argument i=1 and then evaluate the function for the second one i=2 .

So my funcitons without the wrap is as follows:

ff_1 <- function(x,mu=c(2,0.5),sd=c(0.2,0.3)){
      -sum(log(dnorm(x,mu[[1]],sd[[1]]))) 

    return(out)
    }

 ff_2 <- function(x,mu=c(2,0.5),sd=c(0.2,0.3)){
      -sum(log(dnorm(x,mu[[2]],sd[[2]]))) 

    return(out)
    }

and I then need to use two different optim functions for each functions.

I search many website and R help sites but I couldnot find a solution to this question.

Any help please?

Try this one, it's just the way of passing the arguments to optim, I suppose

# given data
set.seed(123)
x <- rnorm(10,2,0.5)

# use vector parOpt instead of specifying two; for convience
# with optim
ff <- function(x, parOpt){
  out  <- -sum(log(dnorm(x, parOpt[1], parOpt[2]))) 
  return(out)
}


# parameters in mu,sd vectors arranged in list
params <- list(set1 = c(2, 0.2), set2 = c(0.5, 0.3))

# output list
out <- list()

for(i in 1:2){
  # pass params (mu and sd) to optim, function ff and the data
  # note, since function ff has x argument, specify that in optim
  out[[i]] <- optim(par = params[[i]], fn=ff ,x=x)

}

Should give something like this:

[[1]]
[[1]]$par
[1] 2.0372546 0.4523918

[[1]]$value
[1] 6.257931

[[1]]$counts
function gradient 
      55       NA 

[[1]]$convergence
[1] 0

[[1]]$message
NULL


[[2]]
[[2]]$par
[1] 2.037165 0.452433

[[2]]$value
[1] 6.257932

[[2]]$counts
function gradient 
      73       NA 

[[2]]$convergence
[1] 0

[[2]]$message
NULL

Hope this helps.

As an alternative, you can find the same solution using the command fitdist of the fitdistrplus package:

library(fitdistrplus)
set.seed(123)
x <- rnorm(10,2,0.5)
mu.start <- c(2,0.5)
sd.start <- c(0.2,0.3)
op <- vector("list",2)
for(i in 1:2){
  op[[i]] <- fitdist(x,"norm", start=c(mu.start[i],sd.start[i]))
}
op

The result is:

[[1]]
Fitting of the distribution ' norm ' by maximum likelihood 
Parameters:
   estimate Std. Error
1 2.0372546  0.1430588
2 0.4523918  0.1011464

[[2]]
Fitting of the distribution ' norm ' by maximum likelihood 
Parameters:
  estimate Std. Error
1 2.037165  0.1430719
2 0.452433  0.1011694

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM