With proper manual weighing you will not see discrepancies.

So the correct way:
X <- model.matrix(~ q + q2 + b + c, mydata)
Although it is generally recommended to use lm.fit and lm.wfit when directly passing to the matrix:
matfit_by_wls <- lm.wfit(X, y, w) matfit_by_ols <- lm.fit(X_tilde, y_tilde)
But when using these internal routines lm.fit and lm.wfit , all the input data must be complete cases without NA , otherwise the main procedure C stats:::C_Cdqrls will complain.
If you still want to use the formula interface rather than the matrix, you can do the following:
#
Reproducible example
Let's use the R built-in trees dataset. Use head(trees) to verify this dataset. There is no NA in this dataset. We strive to fit the model:
Height ~ Girth + Volume
with arbitrary weights from 1 to 2:
set.seed(0); w <- runif(nrow(trees), 1, 2)
We customize this model using weighted regression, either passing weights to lm , or manually converting the data and calling lm without weights:
X <- model.matrix(~ Girth + Volume, trees)
So, indeed, we see identical results.
Alternatively, we can use lm.fit and lm.wfit :
matfit_by_wls <- lm.wfit(X, y, w) matfit_by_ols <- lm.fit(X_tilde, y_tilde)
We can check the coefficients:
matfit_by_wls$coefficients
Again, the results are the same.