some new features
This commit is contained in:
@ -0,0 +1,590 @@
|
||||
"""General linear model
|
||||
|
||||
author: Yichuan Liu
|
||||
"""
|
||||
import numpy as np
|
||||
from numpy.linalg import eigvals, inv, solve, matrix_rank, pinv, svd
|
||||
from scipy import stats
|
||||
import pandas as pd
|
||||
from patsy import DesignInfo
|
||||
|
||||
from statsmodels.compat.pandas import Substitution
|
||||
from statsmodels.base.model import Model
|
||||
from statsmodels.iolib import summary2
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
_hypotheses_doc = \
|
||||
"""hypotheses : list[tuple]
|
||||
Hypothesis `L*B*M = C` to be tested where B is the parameters in
|
||||
regression Y = X*B. Each element is a tuple of length 2, 3, or 4:
|
||||
|
||||
* (name, contrast_L)
|
||||
* (name, contrast_L, transform_M)
|
||||
* (name, contrast_L, transform_M, constant_C)
|
||||
|
||||
containing a string `name`, the contrast matrix L, the transform
|
||||
matrix M (for transforming dependent variables), and right-hand side
|
||||
constant matrix constant_C, respectively.
|
||||
|
||||
contrast_L : 2D array or an array of strings
|
||||
Left-hand side contrast matrix for hypotheses testing.
|
||||
If 2D array, each row is an hypotheses and each column is an
|
||||
independent variable. At least 1 row
|
||||
(1 by k_exog, the number of independent variables) is required.
|
||||
If an array of strings, it will be passed to
|
||||
patsy.DesignInfo().linear_constraint.
|
||||
|
||||
transform_M : 2D array or an array of strings or None, optional
|
||||
Left hand side transform matrix.
|
||||
If `None` or left out, it is set to a k_endog by k_endog
|
||||
identity matrix (i.e. do not transform y matrix).
|
||||
If an array of strings, it will be passed to
|
||||
patsy.DesignInfo().linear_constraint.
|
||||
|
||||
constant_C : 2D array or None, optional
|
||||
Right-hand side constant matrix.
|
||||
if `None` or left out it is set to a matrix of zeros
|
||||
Must has the same number of rows as contrast_L and the same
|
||||
number of columns as transform_M
|
||||
|
||||
If `hypotheses` is None: 1) the effect of each independent variable
|
||||
on the dependent variables will be tested. Or 2) if model is created
|
||||
using a formula, `hypotheses` will be created according to
|
||||
`design_info`. 1) and 2) is equivalent if no additional variables
|
||||
are created by the formula (e.g. dummy variables for categorical
|
||||
variables and interaction terms)
|
||||
"""
|
||||
|
||||
|
||||
def _multivariate_ols_fit(endog, exog, method='svd', tolerance=1e-8):
|
||||
"""
|
||||
Solve multivariate linear model y = x * params
|
||||
where y is dependent variables, x is independent variables
|
||||
|
||||
Parameters
|
||||
----------
|
||||
endog : array_like
|
||||
each column is a dependent variable
|
||||
exog : array_like
|
||||
each column is a independent variable
|
||||
method : str
|
||||
'svd' - Singular value decomposition
|
||||
'pinv' - Moore-Penrose pseudoinverse
|
||||
tolerance : float, a small positive number
|
||||
Tolerance for eigenvalue. Values smaller than tolerance is considered
|
||||
zero.
|
||||
Returns
|
||||
-------
|
||||
a tuple of matrices or values necessary for hypotheses testing
|
||||
|
||||
.. [*] https://support.sas.com/documentation/cdl/en/statug/63033/HTML/default/viewer.htm#statug_introreg_sect012.htm
|
||||
Notes
|
||||
-----
|
||||
Status: experimental and incomplete
|
||||
"""
|
||||
y = endog
|
||||
x = exog
|
||||
nobs, k_endog = y.shape
|
||||
nobs1, k_exog= x.shape
|
||||
if nobs != nobs1:
|
||||
raise ValueError('x(n=%d) and y(n=%d) should have the same number of '
|
||||
'rows!' % (nobs1, nobs))
|
||||
|
||||
# Calculate the matrices necessary for hypotheses testing
|
||||
df_resid = nobs - k_exog
|
||||
if method == 'pinv':
|
||||
# Regression coefficients matrix
|
||||
pinv_x = pinv(x)
|
||||
params = pinv_x.dot(y)
|
||||
|
||||
# inverse of x'x
|
||||
inv_cov = pinv_x.dot(pinv_x.T)
|
||||
if matrix_rank(inv_cov,tol=tolerance) < k_exog:
|
||||
raise ValueError('Covariance of x singular!')
|
||||
|
||||
# Sums of squares and cross-products of residuals
|
||||
# Y'Y - (X * params)'B * params
|
||||
t = x.dot(params)
|
||||
sscpr = np.subtract(y.T.dot(y), t.T.dot(t))
|
||||
return (params, df_resid, inv_cov, sscpr)
|
||||
elif method == 'svd':
|
||||
u, s, v = svd(x, 0)
|
||||
if (s > tolerance).sum() < len(s):
|
||||
raise ValueError('Covariance of x singular!')
|
||||
invs = 1. / s
|
||||
|
||||
params = v.T.dot(np.diag(invs)).dot(u.T).dot(y)
|
||||
inv_cov = v.T.dot(np.diag(np.power(invs, 2))).dot(v)
|
||||
t = np.diag(s).dot(v).dot(params)
|
||||
sscpr = np.subtract(y.T.dot(y), t.T.dot(t))
|
||||
return (params, df_resid, inv_cov, sscpr)
|
||||
else:
|
||||
raise ValueError('%s is not a supported method!' % method)
|
||||
|
||||
|
||||
def multivariate_stats(eigenvals,
|
||||
r_err_sscp,
|
||||
r_contrast, df_resid, tolerance=1e-8):
|
||||
"""
|
||||
For multivariate linear model Y = X * B
|
||||
Testing hypotheses
|
||||
L*B*M = 0
|
||||
where L is contrast matrix, B is the parameters of the
|
||||
multivariate linear model and M is dependent variable transform matrix.
|
||||
T = L*inv(X'X)*L'
|
||||
H = M'B'L'*inv(T)*LBM
|
||||
E = M'(Y'Y - B'X'XB)M
|
||||
|
||||
Parameters
|
||||
----------
|
||||
eigenvals : ndarray
|
||||
The eigenvalues of inv(E + H)*H
|
||||
r_err_sscp : int
|
||||
Rank of E + H
|
||||
r_contrast : int
|
||||
Rank of T matrix
|
||||
df_resid : int
|
||||
Residual degree of freedom (n_samples minus n_variables of X)
|
||||
tolerance : float
|
||||
smaller than which eigenvalue is considered 0
|
||||
|
||||
Returns
|
||||
-------
|
||||
A DataFrame
|
||||
|
||||
References
|
||||
----------
|
||||
.. [*] https://support.sas.com/documentation/cdl/en/statug/63033/HTML/default/viewer.htm#statug_introreg_sect012.htm
|
||||
"""
|
||||
v = df_resid
|
||||
p = r_err_sscp
|
||||
q = r_contrast
|
||||
s = np.min([p, q])
|
||||
ind = eigenvals > tolerance
|
||||
n_e = ind.sum()
|
||||
eigv2 = eigenvals[ind]
|
||||
eigv1 = np.array([i / (1 - i) for i in eigv2])
|
||||
m = (np.abs(p - q) - 1) / 2
|
||||
n = (v - p - 1) / 2
|
||||
|
||||
cols = ['Value', 'Num DF', 'Den DF', 'F Value', 'Pr > F']
|
||||
index = ["Wilks' lambda", "Pillai's trace",
|
||||
"Hotelling-Lawley trace", "Roy's greatest root"]
|
||||
results = pd.DataFrame(columns=cols,
|
||||
index=index)
|
||||
|
||||
def fn(x):
|
||||
return np.real([x])[0]
|
||||
|
||||
results.loc["Wilks' lambda", 'Value'] = fn(np.prod(1 - eigv2))
|
||||
|
||||
results.loc["Pillai's trace", 'Value'] = fn(eigv2.sum())
|
||||
|
||||
results.loc["Hotelling-Lawley trace", 'Value'] = fn(eigv1.sum())
|
||||
|
||||
results.loc["Roy's greatest root", 'Value'] = fn(eigv1.max())
|
||||
|
||||
r = v - (p - q + 1)/2
|
||||
u = (p*q - 2) / 4
|
||||
df1 = p * q
|
||||
if p*p + q*q - 5 > 0:
|
||||
t = np.sqrt((p*p*q*q - 4) / (p*p + q*q - 5))
|
||||
else:
|
||||
t = 1
|
||||
df2 = r*t - 2*u
|
||||
lmd = results.loc["Wilks' lambda", 'Value']
|
||||
lmd = np.power(lmd, 1 / t)
|
||||
F = (1 - lmd) / lmd * df2 / df1
|
||||
results.loc["Wilks' lambda", 'Num DF'] = df1
|
||||
results.loc["Wilks' lambda", 'Den DF'] = df2
|
||||
results.loc["Wilks' lambda", 'F Value'] = F
|
||||
pval = stats.f.sf(F, df1, df2)
|
||||
results.loc["Wilks' lambda", 'Pr > F'] = pval
|
||||
|
||||
V = results.loc["Pillai's trace", 'Value']
|
||||
df1 = s * (2*m + s + 1)
|
||||
df2 = s * (2*n + s + 1)
|
||||
F = df2 / df1 * V / (s - V)
|
||||
results.loc["Pillai's trace", 'Num DF'] = df1
|
||||
results.loc["Pillai's trace", 'Den DF'] = df2
|
||||
results.loc["Pillai's trace", 'F Value'] = F
|
||||
pval = stats.f.sf(F, df1, df2)
|
||||
results.loc["Pillai's trace", 'Pr > F'] = pval
|
||||
|
||||
U = results.loc["Hotelling-Lawley trace", 'Value']
|
||||
if n > 0:
|
||||
b = (p + 2*n) * (q + 2*n) / 2 / (2*n + 1) / (n - 1)
|
||||
df1 = p * q
|
||||
df2 = 4 + (p*q + 2) / (b - 1)
|
||||
c = (df2 - 2) / 2 / n
|
||||
F = df2 / df1 * U / c
|
||||
else:
|
||||
df1 = s * (2*m + s + 1)
|
||||
df2 = s * (s*n + 1)
|
||||
F = df2 / df1 / s * U
|
||||
results.loc["Hotelling-Lawley trace", 'Num DF'] = df1
|
||||
results.loc["Hotelling-Lawley trace", 'Den DF'] = df2
|
||||
results.loc["Hotelling-Lawley trace", 'F Value'] = F
|
||||
pval = stats.f.sf(F, df1, df2)
|
||||
results.loc["Hotelling-Lawley trace", 'Pr > F'] = pval
|
||||
|
||||
sigma = results.loc["Roy's greatest root", 'Value']
|
||||
r = np.max([p, q])
|
||||
df1 = r
|
||||
df2 = v - r + q
|
||||
F = df2 / df1 * sigma
|
||||
results.loc["Roy's greatest root", 'Num DF'] = df1
|
||||
results.loc["Roy's greatest root", 'Den DF'] = df2
|
||||
results.loc["Roy's greatest root", 'F Value'] = F
|
||||
pval = stats.f.sf(F, df1, df2)
|
||||
results.loc["Roy's greatest root", 'Pr > F'] = pval
|
||||
return results
|
||||
|
||||
|
||||
def _multivariate_ols_test(hypotheses, fit_results, exog_names,
|
||||
endog_names):
|
||||
def fn(L, M, C):
|
||||
# .. [1] https://support.sas.com/documentation/cdl/en/statug/63033
|
||||
# /HTML/default/viewer.htm#statug_introreg_sect012.htm
|
||||
params, df_resid, inv_cov, sscpr = fit_results
|
||||
# t1 = (L * params)M
|
||||
t1 = L.dot(params).dot(M) - C
|
||||
# H = t1'L(X'X)^L't1
|
||||
t2 = L.dot(inv_cov).dot(L.T)
|
||||
q = matrix_rank(t2)
|
||||
H = t1.T.dot(inv(t2)).dot(t1)
|
||||
|
||||
# E = M'(Y'Y - B'(X'X)B)M
|
||||
E = M.T.dot(sscpr).dot(M)
|
||||
return E, H, q, df_resid
|
||||
|
||||
return _multivariate_test(hypotheses, exog_names, endog_names, fn)
|
||||
|
||||
|
||||
@Substitution(hypotheses_doc=_hypotheses_doc)
|
||||
def _multivariate_test(hypotheses, exog_names, endog_names, fn):
|
||||
"""
|
||||
Multivariate linear model hypotheses testing
|
||||
|
||||
For y = x * params, where y are the dependent variables and x are the
|
||||
independent variables, testing L * params * M = 0 where L is the contrast
|
||||
matrix for hypotheses testing and M is the transformation matrix for
|
||||
transforming the dependent variables in y.
|
||||
|
||||
Algorithm:
|
||||
T = L*inv(X'X)*L'
|
||||
H = M'B'L'*inv(T)*LBM
|
||||
E = M'(Y'Y - B'X'XB)M
|
||||
where H and E correspond to the numerator and denominator of a univariate
|
||||
F-test. Then find the eigenvalues of inv(H + E)*H from which the
|
||||
multivariate test statistics are calculated.
|
||||
|
||||
.. [*] https://support.sas.com/documentation/cdl/en/statug/63033/HTML
|
||||
/default/viewer.htm#statug_introreg_sect012.htm
|
||||
|
||||
Parameters
|
||||
----------
|
||||
%(hypotheses_doc)s
|
||||
k_xvar : int
|
||||
The number of independent variables
|
||||
k_yvar : int
|
||||
The number of dependent variables
|
||||
fn : function
|
||||
a function fn(contrast_L, transform_M) that returns E, H, q, df_resid
|
||||
where q is the rank of T matrix
|
||||
|
||||
Returns
|
||||
-------
|
||||
results : MANOVAResults
|
||||
"""
|
||||
|
||||
k_xvar = len(exog_names)
|
||||
k_yvar = len(endog_names)
|
||||
results = {}
|
||||
for hypo in hypotheses:
|
||||
if len(hypo) ==2:
|
||||
name, L = hypo
|
||||
M = None
|
||||
C = None
|
||||
elif len(hypo) == 3:
|
||||
name, L, M = hypo
|
||||
C = None
|
||||
elif len(hypo) == 4:
|
||||
name, L, M, C = hypo
|
||||
else:
|
||||
raise ValueError('hypotheses must be a tuple of length 2, 3 or 4.'
|
||||
' len(hypotheses)=%d' % len(hypo))
|
||||
if any(isinstance(j, str) for j in L):
|
||||
L = DesignInfo(exog_names).linear_constraint(L).coefs
|
||||
else:
|
||||
if not isinstance(L, np.ndarray) or len(L.shape) != 2:
|
||||
raise ValueError('Contrast matrix L must be a 2-d array!')
|
||||
if L.shape[1] != k_xvar:
|
||||
raise ValueError('Contrast matrix L should have the same '
|
||||
'number of columns as exog! %d != %d' %
|
||||
(L.shape[1], k_xvar))
|
||||
if M is None:
|
||||
M = np.eye(k_yvar)
|
||||
elif any(isinstance(j, str) for j in M):
|
||||
M = DesignInfo(endog_names).linear_constraint(M).coefs.T
|
||||
else:
|
||||
if M is not None:
|
||||
if not isinstance(M, np.ndarray) or len(M.shape) != 2:
|
||||
raise ValueError('Transform matrix M must be a 2-d array!')
|
||||
if M.shape[0] != k_yvar:
|
||||
raise ValueError('Transform matrix M should have the same '
|
||||
'number of rows as the number of columns '
|
||||
'of endog! %d != %d' %
|
||||
(M.shape[0], k_yvar))
|
||||
if C is None:
|
||||
C = np.zeros([L.shape[0], M.shape[1]])
|
||||
elif not isinstance(C, np.ndarray):
|
||||
raise ValueError('Constant matrix C must be a 2-d array!')
|
||||
|
||||
if C.shape[0] != L.shape[0]:
|
||||
raise ValueError('contrast L and constant C must have the same '
|
||||
'number of rows! %d!=%d'
|
||||
% (L.shape[0], C.shape[0]))
|
||||
if C.shape[1] != M.shape[1]:
|
||||
raise ValueError('transform M and constant C must have the same '
|
||||
'number of columns! %d!=%d'
|
||||
% (M.shape[1], C.shape[1]))
|
||||
E, H, q, df_resid = fn(L, M, C)
|
||||
EH = np.add(E, H)
|
||||
p = matrix_rank(EH)
|
||||
|
||||
# eigenvalues of inv(E + H)H
|
||||
eigv2 = np.sort(eigvals(solve(EH, H)))
|
||||
stat_table = multivariate_stats(eigv2, p, q, df_resid)
|
||||
|
||||
results[name] = {'stat': stat_table, 'contrast_L': L,
|
||||
'transform_M': M, 'constant_C': C,
|
||||
'E': E, 'H': H}
|
||||
return results
|
||||
|
||||
|
||||
class _MultivariateOLS(Model):
|
||||
"""
|
||||
Multivariate linear model via least squares
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
endog : array_like
|
||||
Dependent variables. A nobs x k_endog array where nobs is
|
||||
the number of observations and k_endog is the number of dependent
|
||||
variables
|
||||
exog : array_like
|
||||
Independent variables. A nobs x k_exog array where nobs is the
|
||||
number of observations and k_exog is the number of independent
|
||||
variables. An intercept is not included by default and should be added
|
||||
by the user (models specified using a formula include an intercept by
|
||||
default)
|
||||
|
||||
Attributes
|
||||
----------
|
||||
endog : ndarray
|
||||
See Parameters.
|
||||
exog : ndarray
|
||||
See Parameters.
|
||||
"""
|
||||
_formula_max_endog = None
|
||||
|
||||
def __init__(self, endog, exog, missing='none', hasconst=None, **kwargs):
|
||||
if len(endog.shape) == 1 or endog.shape[1] == 1:
|
||||
raise ValueError('There must be more than one dependent variable'
|
||||
' to fit multivariate OLS!')
|
||||
super().__init__(endog, exog, missing=missing,
|
||||
hasconst=hasconst, **kwargs)
|
||||
|
||||
def fit(self, method='svd'):
|
||||
self._fittedmod = _multivariate_ols_fit(
|
||||
self.endog, self.exog, method=method)
|
||||
return _MultivariateOLSResults(self)
|
||||
|
||||
|
||||
class _MultivariateOLSResults:
|
||||
"""
|
||||
_MultivariateOLS results class
|
||||
"""
|
||||
def __init__(self, fitted_mv_ols):
|
||||
if (hasattr(fitted_mv_ols, 'data') and
|
||||
hasattr(fitted_mv_ols.data, 'design_info')):
|
||||
self.design_info = fitted_mv_ols.data.design_info
|
||||
else:
|
||||
self.design_info = None
|
||||
self.exog_names = fitted_mv_ols.exog_names
|
||||
self.endog_names = fitted_mv_ols.endog_names
|
||||
self._fittedmod = fitted_mv_ols._fittedmod
|
||||
|
||||
def __str__(self):
|
||||
return self.summary().__str__()
|
||||
|
||||
@Substitution(hypotheses_doc=_hypotheses_doc)
|
||||
def mv_test(self, hypotheses=None, skip_intercept_test=False):
|
||||
"""
|
||||
Linear hypotheses testing
|
||||
|
||||
Parameters
|
||||
----------
|
||||
%(hypotheses_doc)s
|
||||
skip_intercept_test : bool
|
||||
If true, then testing the intercept is skipped, the model is not
|
||||
changed.
|
||||
Note: If a term has a numerically insignificant effect, then
|
||||
an exception because of emtpy arrays may be raised. This can
|
||||
happen for the intercept if the data has been demeaned.
|
||||
|
||||
Returns
|
||||
-------
|
||||
results: _MultivariateOLSResults
|
||||
|
||||
Notes
|
||||
-----
|
||||
Tests hypotheses of the form
|
||||
|
||||
L * params * M = C
|
||||
|
||||
where `params` is the regression coefficient matrix for the
|
||||
linear model y = x * params, `L` is the contrast matrix, `M` is the
|
||||
dependent variable transform matrix and C is the constant matrix.
|
||||
"""
|
||||
k_xvar = len(self.exog_names)
|
||||
if hypotheses is None:
|
||||
if self.design_info is not None:
|
||||
terms = self.design_info.term_name_slices
|
||||
hypotheses = []
|
||||
for key in terms:
|
||||
if skip_intercept_test and key == 'Intercept':
|
||||
continue
|
||||
L_contrast = np.eye(k_xvar)[terms[key], :]
|
||||
hypotheses.append([key, L_contrast, None])
|
||||
else:
|
||||
hypotheses = []
|
||||
for i in range(k_xvar):
|
||||
name = 'x%d' % (i)
|
||||
L = np.zeros([1, k_xvar])
|
||||
L[i] = 1
|
||||
hypotheses.append([name, L, None])
|
||||
|
||||
results = _multivariate_ols_test(hypotheses, self._fittedmod,
|
||||
self.exog_names, self.endog_names)
|
||||
|
||||
return MultivariateTestResults(results,
|
||||
self.endog_names,
|
||||
self.exog_names)
|
||||
|
||||
def summary(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class MultivariateTestResults:
|
||||
"""
|
||||
Multivariate test results class
|
||||
|
||||
Returned by `mv_test` method of `_MultivariateOLSResults` class
|
||||
|
||||
Parameters
|
||||
----------
|
||||
results : dict[str, dict]
|
||||
Dictionary containing test results. See the description
|
||||
below for the expected format.
|
||||
endog_names : sequence[str]
|
||||
A list or other sequence of endogenous variables names
|
||||
exog_names : sequence[str]
|
||||
A list of other sequence of exogenous variables names
|
||||
|
||||
Attributes
|
||||
----------
|
||||
results : dict
|
||||
Each hypothesis is contained in a single`key`. Each test must
|
||||
have the following keys:
|
||||
|
||||
* 'stat' - contains the multivariate test results
|
||||
* 'contrast_L' - contains the contrast_L matrix
|
||||
* 'transform_M' - contains the transform_M matrix
|
||||
* 'constant_C' - contains the constant_C matrix
|
||||
* 'H' - contains an intermediate Hypothesis matrix,
|
||||
or the between groups sums of squares and cross-products matrix,
|
||||
corresponding to the numerator of the univariate F test.
|
||||
* 'E' - contains an intermediate Error matrix,
|
||||
corresponding to the denominator of the univariate F test.
|
||||
The Hypotheses and Error matrices can be used to calculate
|
||||
the same test statistics in 'stat', as well as to calculate
|
||||
the discriminant function (canonical correlates) from the
|
||||
eigenvectors of inv(E)H.
|
||||
|
||||
endog_names : list[str]
|
||||
The endogenous names
|
||||
exog_names : list[str]
|
||||
The exogenous names
|
||||
summary_frame : DataFrame
|
||||
Returns results as a MultiIndex DataFrame
|
||||
"""
|
||||
|
||||
def __init__(self, results, endog_names, exog_names):
|
||||
self.results = results
|
||||
self.endog_names = list(endog_names)
|
||||
self.exog_names = list(exog_names)
|
||||
|
||||
def __str__(self):
|
||||
return self.summary().__str__()
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.results[item]
|
||||
|
||||
@property
|
||||
def summary_frame(self):
|
||||
"""
|
||||
Return results as a multiindex dataframe
|
||||
"""
|
||||
df = []
|
||||
for key in self.results:
|
||||
tmp = self.results[key]['stat'].copy()
|
||||
tmp.loc[:, 'Effect'] = key
|
||||
df.append(tmp.reset_index())
|
||||
df = pd.concat(df, axis=0)
|
||||
df = df.set_index(['Effect', 'index'])
|
||||
df.index.set_names(['Effect', 'Statistic'], inplace=True)
|
||||
return df
|
||||
|
||||
def summary(self, show_contrast_L=False, show_transform_M=False,
|
||||
show_constant_C=False):
|
||||
"""
|
||||
Summary of test results
|
||||
|
||||
Parameters
|
||||
----------
|
||||
show_contrast_L : bool
|
||||
Whether to show contrast_L matrix
|
||||
show_transform_M : bool
|
||||
Whether to show transform_M matrix
|
||||
show_constant_C : bool
|
||||
Whether to show the constant_C
|
||||
"""
|
||||
summ = summary2.Summary()
|
||||
summ.add_title('Multivariate linear model')
|
||||
for key in self.results:
|
||||
summ.add_dict({'': ''})
|
||||
df = self.results[key]['stat'].copy()
|
||||
df = df.reset_index()
|
||||
c = list(df.columns)
|
||||
c[0] = key
|
||||
df.columns = c
|
||||
df.index = ['', '', '', '']
|
||||
summ.add_df(df)
|
||||
if show_contrast_L:
|
||||
summ.add_dict({key: ' contrast L='})
|
||||
df = pd.DataFrame(self.results[key]['contrast_L'],
|
||||
columns=self.exog_names)
|
||||
summ.add_df(df)
|
||||
if show_transform_M:
|
||||
summ.add_dict({key: ' transform M='})
|
||||
df = pd.DataFrame(self.results[key]['transform_M'],
|
||||
index=self.endog_names)
|
||||
summ.add_df(df)
|
||||
if show_constant_C:
|
||||
summ.add_dict({key: ' constant C='})
|
||||
df = pd.DataFrame(self.results[key]['constant_C'])
|
||||
summ.add_df(df)
|
||||
return summ
|
||||
Reference in New Issue
Block a user