The way that lm "handles" missing data is that it uses list-wise deletion -- the only cases that are retained & used to estimate the model are the ones for which all of the values in the formula are non-missing.
If you run the code for lm
in OP's post, then summary(lm.D9)
prints an output that includes this line:
Residual standard error: 0.716 on 17 degrees of freedom (1 observation deleted due to missingness)
And this line is buried in the middle of the output, so it's easy to overlook. And if we change the data to
ctl <- c(4.17, rep(NA,9))
then the message printed says
Residual standard error: 0.7937 on 9 degrees of freedom (9 observations deleted due to missingness)
In other words, even though nearly all of the data in ctrl
is missing, there's only the faintest clue to that fact printed by summary
.
Design
My opinion is that silently deleting data from the input is a bad design, because users may think that they're carrying out an analysis of all of the data that they give to lm
, but in fact lm
is only analyzing the complete cases (and silently deleting the rest).
My opinion is that Furthermore,glmnet
's behavior -- raising an error when the data contains missing values -- is the desiredpreferred outcome, because it clearly communicates what happened and why. Even if the user intends to delete the cases with missing data, then there is a simple path to do so: filter the data first and pass only the complete data to glmnet
. But the glmnet
message is transparent about where the problem lies, and puts the user in the position of deciding how to solve it. By contrary, lm
is guessing what the user is trying to do and making a “best effort.”