I would like to perform weighted nonnegative least squares in R (i.e. with the constraint that all fitted coefficients are >=0). The nnls
function in the nnls
package appears not to support weights. Am I correct that I can simulate weights
though within the nnls
function by multiplying both the covariate matrix X
and the dependent variable y
by the square root of the weights
vector, as seems to be indicated here? Or is there better approaches to do this?
1) nnls Yes, it is equivalent since weighted least squares minimizes:
sum( w * (Y - X %*% beta)^2 )
= sum_i( (sqrt(w[i]) * X[i, ] %*% beta - sqrt(w[i]) * Y[i])^2 )
subject to constraints where sum_i means sum over i. Thus sqrt(w[i])
multiplies the ith row of X and the ith element of Y which is equivalent to using sqrt(w) * X
and sqrt(w) * Y
. (Note that these are also equal to diag(sqrt(w)) %*% X
and c(diag(sqrt(w)) %*% Y)
respectively.)
2) CVXR The CVXR package can do weighted non-negative least squares directly. There is an example of performing non-negative least squares in its vignette.
vignette("cvxr_intro")
Just change the objective in the code there to add weights:
objective <- Minimize(sum((w *(Y - X %*% betaHat)^2)))
3) nls nls
which comes with R can do non-negative weighted least squares if you use the port
algorithm with lower bounds of all 0. (In the code below we have started at zero and normally it is not a good idea to start on the boundary but given the linearity here it really doesn't matter.)
zeros <- numeric(ncol(X))
nls(Y ~ X %*% b, start = list(b = zeros), weights = w, lower = zeros, alg = "port")
Run all three approaches to double check the answers.