I'd like to assign a numerical value to a character element of a list, but to an unquoted version of the element so that I can use it in a model formula.
Suppose I have a fully specified model formula that I'll use in, say, the nls function:
m.form <- y ~ b0 + b1*x1 + b2*x2
(I know my example is linear, but that doesn't matter for this). I also have a list of the parameter names and some starting values for each parameter:
params <- c("b0","b1","b2")
startvals <- list(b0=1, b1=1, b2=-1)
I then want to assign a value to a parameter in the params so I can estimate a restricted version of the model, lets say forcing b1==0. Of course, I want to do this by referring to the parameter in the vector params (because I'm going to do a loop over a model with more variables and parameter, estimating the model with the given restriction for each loop iteration).
So I want to do something like this:
params[2] <- 0
summary(nls(m.form,data,startvals[-2])
where I'm trying to replace the parameter name in the formula with numerical 0 and then delete the starting value for that parameter from the startvals since that parameter no longer appears in the model (very likely not the best way to do this!). The above doesn't work, but if instead of the "params[1] <- 0" line I use "b1 <- 0", it does work as intended. But I'll be looping through all the parameters in the model so I don't want to write out the actual parameter name each time. Thanks.
Edit 1
So to be clearer, I need to be able to impose the restriction by referring to the element of the params vector because I'm ultimately going to loop through, each time estimating the model with a different restriction. So, e.g. maybe in the first loop iteration I impose params[2]=0, but in the next, maybe it's params[3]=0.5.
1) It can be done without rewriting the formula by defining the value and removing it from startvals. No packages are used.
set.seed(123)
DF <- data.frame(y = rnorm(25), x1 = rnorm(25), x2 = rnorm(25))
m.form <- y ~ b0 + b1*x1 + b2*x2
startvals <- list(b0=1, b1=1, b2=-1)
b1 <- 0
nls(m.form, DF, start = startvals[-2])
giving:
Nonlinear regression model
model: y ~ b0 + b1 * x1 + b2 * x2
data: DF
b0 b2
-0.03457 0.12139
residual sum-of-squares: 21.18
Number of iterations to convergence: 1
Achieved convergence tolerance: 3.722e-09
2) or if you want to substitute b1 = 0 into the formula anyways then
m.form0 <- do.call("substitute", list(m.form, list(b1 = 0)))
nls(m.form0, DF, start = startvals[-2])
giving:
Nonlinear regression model
model: y ~ b0 + 0 * x1 + b2 * x2
data: DF
b0 b2
-0.03457 0.12139
residual sum-of-squares: 21.18
Number of iterations to convergence: 1
Achieved convergence tolerance: 3.722e-09
If you want to specify these in terms of ix which is a non-empty vector of param index numbers and vals which is an equal length vector of constraint values then
set.seed(123)
DF <- data.frame(y = rnorm(25), x1 = rnorm(25), x2 = rnorm(25))
m.form <- y ~ b0 + b1*x1 + b2*x2
params <- c("b0", "b1", "b2")
startvals <- list(b0 = 1, b1 = 1, b2 = -1)
ix <- 2
vals <- 0
L <- setNames(list(vals), params[ix])
# 1
list2env(L, environment(m.form)) # add constraints to formula's envir
nls(m.form, DF, start = startvals[-ix])
## Nonlinear regression model
## model: y ~ b0 + b1 * x1 + b2 * x2
## ...snip...
# 2
m.form0 <- do.call("substitute", list(m.form, L))
nls(m.form0, DF, start = startvals[-ix])
## Nonlinear regression model
## model: y ~ b0 + 0 * x1 + b2 * x2
## ...sjip...