Missing Data#
All of the models can handle missing data. For performance reasons, the default is not to do any checking for missing data. If, however, you would like for missing data to be handled internally, you can do so by using the missing keyword argument. The default is to do nothing
In [1]: import statsmodels.api as sm
In [2]: data = sm.datasets.longley.load()
In [3]: data.exog = sm.add_constant(data.exog)
# add in some missing data
In [4]: missing_idx = np.array([False] * len(data.endog))
In [5]: missing_idx[[4, 10, 15]] = True
In [6]: data.endog[missing_idx] = np.nan
In [7]: ols_model = sm.OLS(data.endog, data.exog)
In [8]: ols_fit = ols_model.fit()
In [9]: print(ols_fit.params)
const NaN
GNPDEFL NaN
GNP NaN
UNEMP NaN
ARMED NaN
POP NaN
YEAR NaN
dtype: float64
This silently fails and all of the model parameters are NaN, which is probably not what you expected. If you are not sure whether or not you have missing data you can use missing = ‘raise’. This will raise a MissingDataError during model instantiation if missing data is present so that you know something was wrong in your input data.
In [10]: ols_model = sm.OLS(data.endog, data.exog, missing='raise')
---------------------------------------------------------------------------
MissingDataError Traceback (most recent call last)
Cell In[10], line 1
----> 1 ols_model = sm.OLS(data.endog, data.exog, missing='raise')
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/regression/linear_model.py:1004, in OLS.__init__(self, endog, exog, missing, hasconst, **kwargs)
999 msg = (
1000 "Weights are not supported in OLS and will be ignored"
1001 "An exception will be raised in the next version."
1002 )
1003 warnings.warn(msg, ValueWarning, stacklevel=2)
-> 1004 super().__init__(endog, exog, missing=missing, hasconst=hasconst, **kwargs)
1005 if "weights" in self._init_keys:
1006 self._init_keys.remove("weights")
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/regression/linear_model.py:813, in WLS.__init__(self, endog, exog, weights, missing, hasconst, **kwargs)
811 else:
812 weights = weights.squeeze()
--> 813 super().__init__(
814 endog, exog, missing=missing, weights=weights, hasconst=hasconst, **kwargs
815 )
816 nobs = self.exog.shape[0]
817 weights = self.weights
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/regression/linear_model.py:222, in RegressionModel.__init__(self, endog, exog, **kwargs)
221 def __init__(self, endog, exog, **kwargs):
--> 222 super().__init__(endog, exog, **kwargs)
223 self.pinv_wexog: Float64Array | None = None
224 self._data_attr.extend(["pinv_wexog", "wendog", "wexog", "weights"])
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/model.py:286, in LikelihoodModel.__init__(self, endog, exog, **kwargs)
285 def __init__(self, endog, exog=None, **kwargs):
--> 286 super().__init__(endog, exog, **kwargs)
287 self.initialize()
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/model.py:104, in Model.__init__(self, endog, exog, **kwargs)
102 missing = kwargs.pop("missing", "none")
103 hasconst = kwargs.pop("hasconst", None)
--> 104 self.data = self._handle_data(endog, exog, missing, hasconst, **kwargs)
105 self.k_constant = self.data.k_constant
106 self.exog = self.data.exog
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/model.py:145, in Model._handle_data(self, endog, exog, missing, hasconst, **kwargs)
144 def _handle_data(self, endog, exog, missing, hasconst, **kwargs):
--> 145 data = handle_data(endog, exog, missing, hasconst, **kwargs)
146 # kwargs arrays could have changed, easier to just attach here
147 for key in kwargs:
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/data.py:707, in handle_data(endog, exog, missing, hasconst, **kwargs)
704 exog = np.asarray(exog)
706 klass = handle_data_class_factory(endog, exog)
--> 707 return klass(endog, exog=exog, missing=missing, hasconst=hasconst, **kwargs)
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/data.py:76, in ModelData.__init__(self, endog, exog, missing, hasconst, **kwargs)
74 self.formula = kwargs.pop("formula")
75 if missing != "none":
---> 76 arrays, nan_idx = self.handle_missing(endog, exog, missing, **kwargs)
77 self.missing_row_idx = nan_idx
78 self.__dict__.update(arrays) # attach all the data arrays
File /opt/hostedtoolcache/Python/3.14.6/x64/lib/python3.14/site-packages/statsmodels/base/data.py:296, in ModelData.handle_missing(cls, endog, exog, missing, **kwargs)
293 return combined, []
295 elif missing == "raise":
--> 296 raise MissingDataError("NaNs were encountered in the data")
298 elif missing == "drop":
299 nan_mask = ~nan_mask
MissingDataError: NaNs were encountered in the data
If you want statsmodels to handle the missing data by dropping the observations, use missing = ‘drop’.
In [11]: ols_model = sm.OLS(data.endog, data.exog, missing='drop')
We are considering adding a configuration framework so that you can set the option with a global setting.