From 6e8bbe4ef54b7776e84c792d2f4d90b5c2cf4d86 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Thu, 9 Jan 2020 10:22:05 -0600 Subject: [PATCH 01/16] Muting development branch in fork. --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index a54cc66c..c350cc38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,14 +59,6 @@ script: notifications: email: recipients: - - sjsrey@gmail.com - - levi.john.wolf@gmail.com - - dfolch@gmail.com - - daniel.arribas.bel@gmail.com - - weikang9009@gmail.com - - tayoshan@gmail.com - - jgaboardi@gmail.com - - phil.stphns@gmail.com - pedrovma@gmail.com on_success: change on_failure: change From a554840c1d11edc0828a9ccafebe247690386dc1 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 13:05:13 -0600 Subject: [PATCH 02/16] Adding sp_panels.py with GM_KKP to estimate spatial panels. --- spreg/sp_panels.py | 395 ++++++++++++++++++++++++++++++++++++++++ spreg/summary_output.py | 33 +++- spreg/user_output.py | 9 +- spreg/utils.py | 30 ++- 4 files changed, 450 insertions(+), 17 deletions(-) create mode 100755 spreg/sp_panels.py mode change 100644 => 100755 spreg/summary_output.py mode change 100644 => 100755 spreg/user_output.py diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py new file mode 100755 index 00000000..aea54cb7 --- /dev/null +++ b/spreg/sp_panels.py @@ -0,0 +1,395 @@ +''' +Spatial random effects panel model based on: :cite:`KKP2007` + +''' + +__author__ = "Luc Anselin anselin@uchicago.edu, Pedro Amaral pedroamaral@cedeplar.ufmg.br" + +from scipy import sparse as SP +import numpy as np +from . import ols as OLS +from .utils import optim_moments, RegressionPropsY, get_spFilter, spdot +from . import user_output as USER +from . import summary_output as SUMMARY +#import warnings + + +#__all__ = ["GM_KKP"] + + +class BaseGM_KKP(RegressionPropsY): + + ''' + Base GMM method for a spatial random effects panel model based on + Kapoor, Kelejian and Prucha (2007) :cite:`KKP2007`. + + Parameters + ---------- + y : array + n*tx1 array for dependent variable + X : array + Two dimensional array with n*t rows and one column for each + independent (exogenous) variable + (note,must already include constant term) + w : spatial weights object + Spatial weights matrix + full_weights: boolean + Considers different weights for each of the 6 moment + conditions if True or only 2 sets of weights for the + first 3 and the last 3 monent conditions if False (default) + + Attributes + ---------- + n_eq : int + number of time periods + n : int + number of observations in each cross-section + bigy : dictionary + with vectors of dependent variable, one for + each time period + bigX : dictionary + with matrices of explanatory variables, + one for each time period + betas : array + kx1 array of estimated coefficients + u : array + nx1 array of residuals + e_filtered : array + nx1 array of spatially filtered residuals + predy : array + nx1 array of predicted y values + + """ + ''' + + def __init__(self,bigy,bigX,w,full_weights=False): + + # 1a. OLS --> \tilde{\delta} + ols = OLS.BaseOLS(y=bigy, x=bigX) + self.x, self.y, self.n, self.k, self.xtx = ols.x, ols.y, ols.n, ols.k, ols.xtx + N = w.n + T = bigy.shape[0]//N + moments,trace_w2 = _moments_kkp(w.sparse, ols.u, 0) + lambda1,sig_v = optim_moments(moments, all_par=True) + Tw = SP.kron(SP.identity(T),w.sparse) + ub = Tw.dot(ols.u) + ulu = ols.u - lambda1*ub + Q1 = SP.kron(np.ones((T,T))/T,SP.identity(N)) + sig_1 = float(np.dot(ulu.T,Q1.dot(ulu))/N) + #print('initial_lamb_sig:',lambda1,sig_v,sig_1) + #print('theta:', 1 - np.sqrt(sig_v)/ np.sqrt(sig_1)) + Xi_a = SP.diags([(sig_v*sig_v)/(T-1),sig_1*sig_1]) + if full_weights: + Tau = _get_Tau(w.sparse,trace_w2) + else: + Tau = SP.identity(3) + Xi = SP.kron(Xi_a,Tau) + moments_b,trace_w2 = _moments_kkp(w.sparse, ols.u, 1,trace_w2) + G = np.vstack((np.hstack((moments[0],np.zeros((3,1)))),moments_b[0])) + moments6 = [G,np.vstack((moments[1],moments_b[1]))] + lambda2,sig_vb,sig_1b = optim_moments(moments6, vcX=Xi.toarray(), all_par=True, start=[lambda1,sig_v,sig_1]) + # 2a. reg -->\hat{betas} + theta = 1 - np.sqrt(sig_vb)/np.sqrt(sig_1b) + #print('theta:', theta) + gls_w = SP.identity(N*T) - theta*Q1 + + #With omega + xs = gls_w.dot(get_spFilter(w, lambda2, bigX)) + ys = gls_w.dot(get_spFilter(w, lambda2, bigy)) + ols_s = OLS.BaseOLS(y=ys, x=xs) + self.predy = spdot(self.x, ols_s.betas) + self.u = self.y - self.predy + self.vm = ols_s.vm #Check + self.betas = np.vstack((ols_s.betas, lambda2, sig_vb, sig_1b)) + self.e_filtered = self.u - lambda2 * SP.kron(SP.identity(T), + w.sparse).dot(self.u) + self.n_eq, self.n = T, N + self._cache = {} + +class GM_KKP(BaseGM_KKP): + + ''' + GMM method for a spatial random effects panel model based on + Kapoor, Kelejian and Prucha (2007) :cite:`KKP2007`. + + Parameters + ---------- + y : array + n*tx1 or nxt array for dependent variable + X : array + Two dimensional array with n*t rows and k columns for + independent (exogenous) variable or n rows and k*t columns + (note, must not include a constant term) + w : spatial weights object + Spatial weights matrix, nxn + full_weights: boolean + Considers different weights for each of the 6 moment + conditions if True or only 2 sets of weights for the + first 3 and the last 3 moment conditions if False (default) + name_y : string or list of strings + Name of dependent variable for use in output + name_x : list of strings + Names of independent variables for use in output + name_w : string + Name of weights matrix for use in output + name_ds : string + Name of dataset for use in output + + Attributes + ---------- + n_eq : int + number of time periods + n : int + number of observations in each cross-section + bigy : dictionary + with vectors of dependent variable, one for + each time period + bigX : dictionary + with matrices of explanatory variables, + one for each time period + betas : array + kx1 array of estimated coefficients + u : array + nx1 array of residuals + e_filtered : array + nx1 array of spatially filtered residuals + predy : array + nx1 array of predicted y values + + """ + + Examples + -------- + We first need to import the needed modules, namely numpy to convert the + data we read into arrays that ``spreg`` understands and ``pysal`` to + perform all the analysis. + + >>> import spreg + >>> import numpy as np + >>> import libpysal + + Open data on NCOVR US County Homicides (3085 areas) using libpysal.io.open(). + This is the DBF associated with the NAT shapefile. Note that + libpysal.io.open() also reads data in CSV format; The GM_KKP function requires + data to be passed in as numpy arrays, hence the user can read their + data in using any method. + + >>> db = libpysal.io.open(libpysal.examples.get_path('NAT.dbf'),'r') + + Extract the HR (homicide rates) data in the 70's, 80's and 90's from the DBF file + and make it the dependent variable for the regression. Note that the data can also + be passed in the long format instead of wide format (i.e. a vector with n*t rows + and a single column for the dependent variable and a matrix of dimension n*txk + for the independent variables). + + >>> name_y = ['HR70','HR80','HR90'] + >>> y = np.array([db.by_col(name) for name in name_y]).T + + Extract RD and PS in the same time periods from the DBF to be used as + independent variables in the regression. Note that PySAL requires this to + be an nxk*t numpy array, where k is the number of independent variables (not + including a constant) and t is the number of time periods. Data must be + organized in a way that all time periods of a given variable are side-by-side + and in the correct time order. + By default a vector of ones will be added to the independent variables passed in. + + >>> name_x = ['RD70','RD80','RD90','PS70','PS80','PS90'] + >>> x = np.array([db.by_col(name) for name in name_x]).T + + Since we want to run a spatial error panel model, we need to specify the spatial + weights matrix that includes the spatial configuration of the observations + into the error component of the model. To do that, we can open an already + existing gal file or create a new one. In this case, we will create one + from ``NAT.shp``. + + >>> w = libpysal.weights.Queen.from_shapefile(libpysal.examples.get_path("NAT.shp")) + + Unless there is a good reason not to do it, the weights have to be + row-standardized so every row of the matrix sums to one. Among other + things, his allows to interpret the spatial lag of a variable as the + average value of the neighboring observations. In PySAL, this can be + easily performed in the following way: + + >>> w.transform = 'r' + + We are all set with the preliminaries, we are good to run the model. In this + case, we will need the variables and the weights matrix. If we want to + have the names of the variables printed in the output summary, we will + have to pass them in as well, although this is optional. In this example + we set full_weights to False (the default), indicating that we will use + only 2 sets of moments weights for the first 3 and the last 3 moment conditions. + + >>> reg = GM_KKP(y,x,w,full_weights=False,name_y=name_y, name_x=name_x) + Warning: Assuming time data is in wide format, i.e. y[0] refers to T0, y[1], refers to T1, etc. + Similarly, assuming x[0:k] refers to independent variables for T0, x[k+1:2k] refers to T1, etc. + + Once we have run the model, we can explore a little bit the output. We can + either request a printout of the results with the command print(reg.summary) or + check out the individual attributes of GM_KKP: + + >>> print(reg.name_x) + ['CONSTANT', 'RD', 'PS', 'lambda', ' sigma2_v', 'sigma2_1'] + + The attribute reg.betas contains all the coefficients: betas, the spatial error + coefficient lambda, sig2_v and sig2_1: + + >>> print(np.around(reg.betas,4)) + [[ 6.4922] + [ 3.6245] + [ 1.3119] + [ 0.4178] + [22.8191] + [39.9099]] + + Finally, we can check the standard erros of the betas: + >>> print(np.around(np.sqrt(reg.vm.diagonal().reshape(3,1)),4)) + [[0.1127] + [0.0877] + [0.0853]] + + ''' + + def __init__(self, y, x, w, full_weights=False, + vm=False, name_y=None, name_x=None, + name_w=None, name_ds=None): + n_rows = USER.check_arrays(y, x) + bigy, bigx, name_y, name_x = _get_panel_data(y, x, w, name_y, name_x) + USER.check_weights(w, bigy, w_required=True, time=True) + x_constant = USER.check_constant(bigx) + BaseGM_KKP.__init__( + self, bigy, x_constant, w, full_weights=full_weights) + self.title = "GM SPATIAL ERROR PANEL MODEL - RANDOM EFFECTS (KKP)" + self.name_ds = USER.set_name_ds(name_ds) + self.name_y = USER.set_name_y(name_y) + self.name_x = USER.set_name_x(name_x, x) + self.name_x.extend(['lambda',' sigma2_v', 'sigma2_1']) + self.name_w = USER.set_name_w(name_w, w) + SUMMARY.GM_Panels(reg=self, w=w, vm=vm) + +def _moments_kkp(ws, u, i, trace_w2=None): + ''' + Compute G and g matrices for the KKP model. + ... + + Parameters + ---------- + + ws : Sparse matrix + Spatial weights sparse matrix + + u : array + Residuals. nx1 array assumed to be aligned with w + + i : integer + 0 if Q0, 1 if Q1 + + Attributes + ---------- + + moments : list + List of two arrays corresponding to the matrices 'G' and + 'g', respectively. + + + ''' + N = ws.shape[0] + T = u.shape[0]//N + if i == 0: + Q = SP.kron(SP.identity(T) - np.ones((T,T))/T,SP.identity(N)) + else: + Q = SP.kron(np.ones((T,T))/T,SP.identity(N)) + Tw = SP.kron(SP.identity(T),ws) + ub = Tw.dot(u) + ubb = Tw.dot(ub) + Qu = Q.dot(u) + Qub = Q.dot(ub) + Qubb = Q.dot(ubb) + G11 = float(2*np.dot(u.T,Qub)) + G12 = float(-np.dot(ub.T,Qub)) + G21 = float(2*np.dot(ubb.T,Qub)) + G22 = float(-np.dot(ubb.T,Qubb)) + G31 = float(np.dot(u.T,Qubb)+np.dot(ub.T,Qub)) + G32 = float(-np.dot(ub.T,Qubb)) + if trace_w2 == None: + trace_w2 = (ws.power(2)).sum() + G23 = ((T-1)**(1-i))*trace_w2 + if i == 0: + G = np.array([[G11,G12,N*(T-1)**(1-i)],[G21,G22,G23],[G31,G32,0]])/(N*(T-1)**(1-i)) + else: + G = np.array([[G11,G12,0,N*(T-1)**(1-i)],[G21,G22,0,G23],[G31,G32,0,0]])/(N*(T-1)**(1-i)) + g1 = float(np.dot(u.T,Qu)) + g2 = float(np.dot(ub.T,Qub)) + g3 = float(np.dot(u.T,Qub)) + g = np.array([[g1,g2,g3]]).T / (N*(T-1)**(1-i)) + return [G, g],trace_w2 + + +def _get_Tau(ws, trace_w2): + N = ws.shape[0] + T12 = 2*trace_w2/N + wtw = ws.T.dot(ws) + T22 = wtw.power(2).sum() + wtpw = ws.T + ws + T23 = wtw.multiply(wtpw).sum() + d_wwpwtw = ws.multiply(ws.T).sum(0)+wtw.diagonal() + T33 = d_wwpwtw.sum() + Tau = np.array([[2*N,T12,0],[T12,T22,T23],[0,T23,T33]])/N + return Tau + +def _get_panel_data(y, x, w, name_y, name_x): + ''' + Performs some checks on the data structure and converts from wide to long if needed. + ''' + + if y.shape[0]/w.n != y.shape[0]//w.n: + raise Exception("y must be ntx1 or nxt, and w must be an nxn PySAL W object.") + N,T = y.shape[0],y.shape[1] + k = x.shape[1] // T + if x.shape[0] != N and x.shape[0] != N*T: + raise Exception("X must have either n rows and k*t columns or n*t rows and k columns.") + if x.shape[1] != k and x.shape[1] != k*T: + raise Exception("X must have either n rows and k*t columns or n*t rows and k columns.") + if y.shape[1] > 1: + message = "Assuming time data is in wide format, i.e. y[0] refers to T0, y[1], refers to T1, etc." \ + "\n Similarly, assuming x[0:k] refers to independent variables for T0, x[k+1:2k] refers to T1, etc." + print("Warning: "+ message) + #warnings.warn(message) + + if y.shape[1] != T: + raise Exception("y in wide format must have t columns and be compatible with x's k*t columns.") + + bigy = y.reshape((y.size,1),order="F") + + bigx = x[:,0:T].reshape((N*T,1),order='F') + for i in range(1,k): + bigx = np.hstack((bigx,x[:,T*i:T*(i+1)].reshape((N*T,1),order='F'))) + else: + bigy, bigx = y, x + + if name_y: + if not isinstance(name_y, str) and not isinstance(name_y, list): + raise Exception("name_y must either be strings or a list of strings.") + if len(name_y) > 1 and isinstance(name_y, list): + name_y = ''.join([i for i in name_y[0] if not i.isdigit()]) + if len(name_y) == 1 and isinstance(name_y, list): + name_y = name_y[0] + if name_x: + if len(name_x) != k*T and len(name_x) != k: + raise Exception("Names of columns in X must have exactly either k or k*t elements.") + if len(name_x) > k: + name_bigx = [] + for i in range(k): + name_bigx.append(''.join([j for j in name_x[i*T] if not j.isdigit()])) + name_x = name_bigx + + return bigy, bigx, name_y, name_x + +def _test(): + import doctest + start_suppress = np.get_printoptions()['suppress'] + np.set_printoptions(suppress=True) + doctest.testmod() + np.set_printoptions(suppress=start_suppress) + +if __name__ == '__main__': + _test() diff --git a/spreg/summary_output.py b/spreg/summary_output.py old mode 100644 new mode 100755 index e2e04db7..b46e9d3e --- a/spreg/summary_output.py +++ b/spreg/summary_output.py @@ -685,6 +685,20 @@ def SUR(reg, nonspat_diag=True, spat_diag=False, regimes=False,\ summary_SUR(reg=reg) +def GM_Panels(reg, vm, w, regimes=False): + reg.__summary = {} + # compute diagnostics and organize summary output + beta_diag(reg, None) + # build coefficients table body + beta_position = summary_coefs_somex(reg, reg.z_stat) + summary_coefs_lambda(reg, reg.z_stat) + if regimes: + summary_regimes(reg) + summary_warning(reg) + summary(reg=reg, vm=vm, instruments=False, + nonspat_diag=False, spat_diag=False) + + ############################################################################## @@ -899,19 +913,19 @@ def summary_SUR(reg, short_intro=True): reg.summary = summary -def _get_var_indices(reg, lambd=False): +def _get_var_indices(reg, zt_stat, lambd=False): try: var_names = reg.name_z except: var_names = reg.name_x last_v = len(var_names) if lambd: - last_v += -1 + last_v += len(zt_stat)-len(reg.betas) indices = [] try: kf = reg.kf if lambd: - kf += -1 + kf += -len(zt_stat)-len(reg.betas) krex = reg.kr - reg.kryd try: kfyd = reg.yend.shape[1] - reg.nr * reg.kryd @@ -1016,7 +1030,7 @@ def summary_coefs_intro(reg): def summary_coefs_allx(reg, zt_stat, lambd=False): strSummary = "" - var_names, indices = _get_var_indices(reg, lambd) + var_names, indices = _get_var_indices(reg, zt_stat, lambd) for i in indices: strSummary += "%20s %12.7f %12.7f %12.7f %12.7f\n" \ % (var_names[i], reg.betas[i][0], reg.std_err[i], zt_stat[i][0], zt_stat[i][1]) @@ -1073,7 +1087,7 @@ def summary_coefs_somex(reg, zt_stat): the lambda term """ strSummary = "" - var_names, indices = _get_var_indices(reg, lambd=True) + var_names, indices = _get_var_indices(reg, zt_stat, lambd=True) for i in indices: strSummary += "%20s %12.7f %12.7f %12.7f %12.7f\n" \ % (reg.name_x[i], reg.betas[i][0], reg.std_err[i], zt_stat[i][0], zt_stat[i][1]) @@ -1084,7 +1098,7 @@ def summary_coefs_somex(reg, zt_stat): ''' def summary_coefs_yend(reg, zt_stat, lambd=False): strSummary = "" - indices = _get_var_indices(reg, lambd) + indices = _get_var_indices(reg, zt_stat, lambd) for i in indices: strSummary += "%20s %12.7f %12.7f %12.7f %12.7f\n" \ % (reg.name_z[i],reg.betas[i][0],reg.std_err[i],zt_stat[i][0],zt_stat[i][1]) @@ -1101,8 +1115,11 @@ def summary_coefs_lambda(reg, zt_stat): reg.__summary['summary_coefs'] += "%20s %12.7f %12.7f %12.7f %12.7f\n" \ % (name_var[-1], reg.betas[-1][0], reg.std_err[-1], zt_stat[-1][0], zt_stat[-1][1]) else: - reg.__summary[ - 'summary_coefs'] += "%20s %12.7f \n" % (name_var[-1], reg.betas[-1][0]) + n_coef = len(reg.betas) - len(zt_stat) + for i in range(n_coef): + k = i - n_coef + reg.__summary[ + 'summary_coefs'] += "%20s %12.7f \n" % (name_var[k], reg.betas[k][0]) def summary_coefs_instruments(reg, sur=None): diff --git a/spreg/user_output.py b/spreg/user_output.py old mode 100644 new mode 100755 index 6fd84482..87813f44 --- a/spreg/user_output.py +++ b/spreg/user_output.py @@ -392,7 +392,7 @@ def check_y(y, n): raise Exception("y must be a single column array matching the length of other arrays") -def check_weights(w, y, w_required=False): +def check_weights(w, y, w_required=False, time=False): """Check if the w parameter passed by the user is a libpysal.W object and check that its dimensionality matches the y parameter. Note that this check is not performed if w set to None. @@ -405,6 +405,11 @@ def check_weights(w, y, w_required=False): y : numpy array Any shape numpy array can be passed. Note: if y passed check_arrays, then it will be valid for this function + w_required : boolean + True if a W matrix is required, False (default) if not. + time : boolean + True if data contains a time dimension. + False (default) if not. Returns ------- @@ -436,7 +441,7 @@ def check_weights(w, y, w_required=False): if not isinstance(w, weights.W): from warnings import warn warn("w must be API-compatible pysal weights object") - if w.n != y.shape[0]: + if w.n != y.shape[0] and time == False: raise Exception("y must be nx1, and w must be an nxn PySAL W object") diag = w.sparse.diagonal() # check to make sure all entries equal 0 diff --git a/spreg/utils.py b/spreg/utils.py index 3a1e8da1..c04ce6d3 100755 --- a/spreg/utils.py +++ b/spreg/utils.py @@ -322,7 +322,7 @@ def _moments2eqs(A1, s, u): return [G, g] -def optim_moments(moments_in, vcX=np.array([0])): +def optim_moments(moments_in, vcX=np.array([0]), all_par=False, start=None): """ Optimization of moments ... @@ -333,9 +333,14 @@ def optim_moments(moments_in, vcX=np.array([0])): moments : Moments Instance of gmm_utils.moments_het with G and g vcX : array - Optional. 2x2 array with the Variance-Covariance matrix to be used as + Optional. Array with the Variance-Covariance matrix to be used as weights in the optimization (applies Cholesky decomposition). Set empty by default. + all_par : boolean + Optional. Whether to return all parameters from + solution or just the 1st. Default is 1st only. + start : list + List with initial values for the optimization Returns ------- @@ -365,13 +370,20 @@ def optim_moments(moments_in, vcX=np.array([0])): if moments[0].shape[0] == 3: optim_par = lambda par: foptim_par( np.array([[float(par[0]), float(par[0]) ** 2., float(par[1])]]).T, moments) - start = [0.0, 0.0] + start = [0.0, 1.0] bounds = [(-1.0, 1.0), (0.0, None)] + if moments[0].shape[1] == 4: + optim_par = lambda par: foptim_par( + np.array([[float(par[0]), float(par[0]) ** 2., float(par[1]), float(par[2])]]).T, moments) + if not start: + start = [0.0, 1.0, 1.0] + bounds = [(-1.0, 1.0), (0.0, None), (0.0, None)] lambdaX = op.fmin_l_bfgs_b( optim_par, start, approx_grad=True, bounds=bounds) + if all_par: + return lambdaX[0] return lambdaX[0][0] - def foptim_par(par, moments): """ Preparation of the function of moments for minimization @@ -434,12 +446,16 @@ def get_spFilter(w, lamb, sf): ''' try: - result = sf - lamb * (w.sparse * sf) + ws = w.sparse except: - result = sf - lamb * (w * sf) + ws = w + T = sf.shape[0] // ws.shape[0] + if T == 1: + result = sf - lamb * (ws * sf) + else: + result = sf - lamb * SP.kron(SP.identity(T),ws).dot(sf) return result - def get_lags(w, x, w_lags): ''' Calculates a given order of spatial lags and all the smaller orders From 1c073d56bf957c6ea180ede2463e04bd6333747a Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 13:06:03 -0600 Subject: [PATCH 03/16] Minor updates. --- spreg/error_sp_het.py | 4 ++++ 1 file changed, 4 insertions(+) mode change 100644 => 100755 spreg/error_sp_het.py diff --git a/spreg/error_sp_het.py b/spreg/error_sp_het.py old mode 100644 new mode 100755 index ac03144f..5e213d90 --- a/spreg/error_sp_het.py +++ b/spreg/error_sp_het.py @@ -326,6 +326,10 @@ class GM_Error_Het(BaseGM_Error_Het): [ 0.7105 0.3681] [-0.5588 0.1616] [ 0.4118 0.168 ]] + + Alternatively, we can have a summary of the output by typing: + print(reg.summary) + """ def __init__(self, y, x, w, From af0d36482c475c38915f7abf3833e22d327698f8 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 13:15:17 -0600 Subject: [PATCH 04/16] Adding KKP reference. --- doc/_static/references.bib | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/_static/references.bib b/doc/_static/references.bib index 0dcfff39..64bc066d 100644 --- a/doc/_static/references.bib +++ b/doc/_static/references.bib @@ -236,6 +236,14 @@ @article{Kelejian1999 Volume = {40}, Year = {1999}} +@article{KKP2007, + Author = {Kapoor, M and Kelejian, H H and Prucha, I R}, + Journal = {Journal of Econometrics}, + Pages = {97--130}, + Title = {Panel data models with spatially correlated error components}, + Volume = {140}, + Year = {2007}} + @book{Greene2003, Author = {Greene, William H}, Publisher = {Pearson Education India}, From 2b2ab5a76eeea82632b63309f44c0e95562d9d4e Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 13:23:24 -0600 Subject: [PATCH 05/16] Restore Travis. --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index c350cc38..a54cc66c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,6 +59,14 @@ script: notifications: email: recipients: + - sjsrey@gmail.com + - levi.john.wolf@gmail.com + - dfolch@gmail.com + - daniel.arribas.bel@gmail.com + - weikang9009@gmail.com + - tayoshan@gmail.com + - jgaboardi@gmail.com + - phil.stphns@gmail.com - pedrovma@gmail.com on_success: change on_failure: change From 8beb620b138fd428e4ba0934c57bd6e370027450 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 13:57:00 -0600 Subject: [PATCH 06/16] Adding panel branch for Travis testing. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a54cc66c..3026a506 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ sudo: true branches: only: - master + - panel python: - 3.6 From db5672dfcde9ac9df838933d462256c3119b7b2f Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 14:02:10 -0600 Subject: [PATCH 07/16] Fixing GM_KKP example. --- spreg/sp_panels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py index aea54cb7..e7dd3f6c 100755 --- a/spreg/sp_panels.py +++ b/spreg/sp_panels.py @@ -164,7 +164,7 @@ class GM_KKP(BaseGM_KKP): data we read into arrays that ``spreg`` understands and ``pysal`` to perform all the analysis. - >>> import spreg + >>> from spreg import GM_KKP >>> import numpy as np >>> import libpysal From 7cd9c04991ac3e73918f42670ff5c339bc609d8a Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Mon, 20 Jan 2020 14:48:50 -0600 Subject: [PATCH 08/16] Adding testing suite and documentation. --- doc/api.rst | 12 ++++++- spreg/__init__.py | 4 ++- spreg/sp_panels.py | 4 +-- spreg/tests/__init__.py | 0 spreg/tests/test_sp_panels.py | 66 +++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 4 deletions(-) mode change 100644 => 100755 spreg/tests/__init__.py create mode 100644 spreg/tests/test_sp_panels.py diff --git a/doc/api.rst b/doc/api.rst index b55effb7..d7a22181 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -63,7 +63,7 @@ Regimes models are variants of spatial regression models which allow for structu Seemingly-Unrelated Regressions -------------------------------- -Seeimingly-unrelated regression models are a generalization of linear regression. These models (and their spatial generalizations) allow for correlation in the residual terms between groups that use the same model. In spatial Seeimingly-Unrelated Regressions, the error terms across groups are allowed to exhibit a structured type of correlation: spatail correlation. +Seemingly-unrelated regression models are a generalization of linear regression. These models (and their spatial generalizations) allow for correlation in the residual terms between groups that use the same model. In spatial Seeimingly-Unrelated Regressions, the error terms across groups are allowed to exhibit a structured type of correlation: spatial correlation. .. autosummary:: :toctree: generated/ @@ -74,6 +74,16 @@ Seeimingly-unrelated regression models are a generalization of linear regression spreg.SURlagIV spreg.ThreeSLS +Spatial Panel Models +-------------------- + +Spatial panel models allow for evaluating correlation in both spatial and time dimensions. + +.. autosummary:: + :toctree: generated/ + + spreg.GM_KKP + Diagnostics ----------- diff --git a/spreg/__init__.py b/spreg/__init__.py index a8bf82b2..7fdb12cf 100644 --- a/spreg/__init__.py +++ b/spreg/__init__.py @@ -1,3 +1,4 @@ + __version__ = "1.1.1" from .ols import * from .diagnostics import * @@ -27,4 +28,5 @@ from .sur_utils import * from .utils import * from .regimes import * -from .sputils import * \ No newline at end of file +from .sputils import * +from .sp_panels import * diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py index e7dd3f6c..f7280842 100755 --- a/spreg/sp_panels.py +++ b/spreg/sp_panels.py @@ -14,7 +14,7 @@ #import warnings -#__all__ = ["GM_KKP"] +__all__ = ["GM_KKP"] class BaseGM_KKP(RegressionPropsY): @@ -261,7 +261,7 @@ def __init__(self, y, x, w, full_weights=False, self.title = "GM SPATIAL ERROR PANEL MODEL - RANDOM EFFECTS (KKP)" self.name_ds = USER.set_name_ds(name_ds) self.name_y = USER.set_name_y(name_y) - self.name_x = USER.set_name_x(name_x, x) + self.name_x = USER.set_name_x(name_x, bigx) self.name_x.extend(['lambda',' sigma2_v', 'sigma2_1']) self.name_w = USER.set_name_w(name_w, w) SUMMARY.GM_Panels(reg=self, w=w, vm=vm) diff --git a/spreg/tests/__init__.py b/spreg/tests/__init__.py old mode 100644 new mode 100755 diff --git a/spreg/tests/test_sp_panels.py b/spreg/tests/test_sp_panels.py new file mode 100644 index 00000000..1bae1f62 --- /dev/null +++ b/spreg/tests/test_sp_panels.py @@ -0,0 +1,66 @@ +import unittest +import numpy as np +import libpysal +from libpysal.common import RTOL +from spreg.sp_panels import * +ATOL = 1e-12 + + +class Test_GM_KKP(unittest.TestCase): + def setUp(self): + self.db = libpysal.io.open(libpysal.examples.get_path('NAT.dbf'),'r') + self.w = libpysal.weights.Queen.from_shapefile(libpysal.examples.get_path("NAT.shp")) + self.w.transform = 'r' + y_var0 = ['HR70','HR80','HR90'] + x_var0 = ['RD70','RD80','RD90','PS70','PS80','PS90'] + self.y = np.array([self.db.by_col(name) for name in y_var0]).T + self.x = np.array([self.db.by_col(name) for name in x_var0]).T + + + def test_wide_ident(self): + reg = GM_KKP(self.y,self.x,self.w,full_weights=False,name_y=['HR70','HR80','HR90'], name_x=['RD70','RD80','RD90','PS70','PS80','PS90']) + np.testing.assert_allclose(reg.betas,np.array([[ 6.49221562], + [ 3.62445753], + [ 1.31187779], + [ 0.41777589], + [22.81908224], + [39.90993228]]),RTOL) + np.testing.assert_allclose(reg.vm,np.array([[ 1.26948117e-02, -1.98160325e-06, 7.38157674e-05], + [-1.98160325e-06, 7.69961725e-03, 1.13099329e-03], + [ 7.38157674e-05, 1.13099329e-03, 7.26783636e-03]]),RTOL) + np.testing.assert_equal(reg.name_x, ['CONSTANT', 'RD', 'PS', 'lambda', ' sigma2_v', 'sigma2_1']) + np.testing.assert_equal(reg.name_y, 'HR') + + def test_wide_full(self): + reg = GM_KKP(self.y,self.x,self.w,full_weights=True) + + np.testing.assert_allclose(reg.betas,np.array([[ 6.49193589], + [ 3.55740165], + [ 1.29462748], + [ 0.4263399 ], + [22.47241979], + [45.82593532]]),RTOL) + np.testing.assert_allclose(reg.vm,np.array([[ 1.45113773e-02, -2.14882672e-06, 8.54997693e-05], + [-2.14882672e-06, 8.41929187e-03, 1.24553497e-03], + [ 8.54997693e-05, 1.24553497e-03, 8.12448812e-03]]),RTOL) + + def test_long_ident(self): + bigy = self.y.reshape((self.y.size,1),order="F") + bigx = self.x[:,0:3].reshape((self.x.shape[0]*3,1),order='F') + bigx = np.hstack((bigx,self.x[:,3:6].reshape((self.x.shape[0]*3,1),order='F'))) + reg = GM_KKP(bigy,bigx,self.w,full_weights=False,name_y=['HR'], name_x=['RD','PS']) + + np.testing.assert_allclose(reg.betas,np.array([[ 6.49221562], + [ 3.62445753], + [ 1.31187779], + [ 0.41777589], + [22.81908224], + [39.90993228]]),RTOL) + np.testing.assert_allclose(reg.vm,np.array([[ 1.26948117e-02, -1.98160325e-06, 7.38157674e-05], + [-1.98160325e-06, 7.69961725e-03, 1.13099329e-03], + [ 7.38157674e-05, 1.13099329e-03, 7.26783636e-03]]),RTOL) + np.testing.assert_equal(reg.name_x, ['CONSTANT', 'RD', 'PS', 'lambda', ' sigma2_v', 'sigma2_1']) + np.testing.assert_equal(reg.name_y, 'HR') +if __name__ == '__main__': + unittest.main() + From a8d2f60fde4eef41826bbc20ac61862f18a36cb1 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Tue, 21 Jan 2020 13:07:52 -0600 Subject: [PATCH 09/16] Adding regimes for KKP (X variables only). --- spreg/sp_panels.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py index f7280842..e23a4062 100755 --- a/spreg/sp_panels.py +++ b/spreg/sp_panels.py @@ -11,6 +11,7 @@ from .utils import optim_moments, RegressionPropsY, get_spFilter, spdot from . import user_output as USER from . import summary_output as SUMMARY +from . import regimes as REGI #import warnings @@ -106,7 +107,7 @@ def __init__(self,bigy,bigX,w,full_weights=False): self.n_eq, self.n = T, N self._cache = {} -class GM_KKP(BaseGM_KKP): +class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): ''' GMM method for a spatial random effects panel model based on @@ -250,22 +251,44 @@ class GM_KKP(BaseGM_KKP): ''' def __init__(self, y, x, w, full_weights=False, - vm=False, name_y=None, name_x=None, - name_w=None, name_ds=None): + regimes=None, vm=False, name_y=None, name_x=None, + name_w=None, name_ds=None, name_regimes=None): n_rows = USER.check_arrays(y, x) bigy, bigx, name_y, name_x = _get_panel_data(y, x, w, name_y, name_x) USER.check_weights(w, bigy, w_required=True, time=True) x_constant = USER.check_constant(bigx) - BaseGM_KKP.__init__( - self, bigy, x_constant, w, full_weights=full_weights) self.title = "GM SPATIAL ERROR PANEL MODEL - RANDOM EFFECTS (KKP)" + self.name_x = USER.set_name_x(name_x, bigx) + + if regimes is not None: + self.regimes = regimes + self.name_regimes = USER.set_name_ds(name_regimes) + regimes_l = self._set_regimes(w, bigy.shape[0]) + print(x_constant.shape, len(regimes_l)) + x_constant, self.name_x = REGI.Regimes_Frame.__init__(self, x_constant, + regimes_l, constant_regi=False, cols2regi='all', names=self.name_x) + self.title += " WITH REGIMES" + + BaseGM_KKP.__init__(self, bigy, x_constant, w, full_weights=full_weights) self.name_ds = USER.set_name_ds(name_ds) self.name_y = USER.set_name_y(name_y) - self.name_x = USER.set_name_x(name_x, bigx) self.name_x.extend(['lambda',' sigma2_v', 'sigma2_1']) self.name_w = USER.set_name_w(name_w, w) SUMMARY.GM_Panels(reg=self, w=w, vm=vm) + def _set_regimes(self,w,n_rows): + self.constant_regi = 'many' + self.cols2regi = 'all' + self.regime_err_sep = False + self.regimes_set = REGI._get_regimes_set(self.regimes) + if len(self.regimes) == w.n: + regimes_l = self.regimes * (n_rows//w.n) + elif len(self.regimes) == n_rows: + regimes_l = self.regimes + else: + raise Exception("The lenght of 'regimes' must be either equal to n or n*t.") + return regimes_l + def _moments_kkp(ws, u, i, trace_w2=None): ''' Compute G and g matrices for the KKP model. From 8cd0c63ba1b616410bb2895f1e9110551b1a7a37 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Tue, 21 Jan 2020 15:02:13 -0600 Subject: [PATCH 10/16] Adding documentation and tests for regimes within KKP. --- spreg/regimes.py | 4 ++-- spreg/sp_panels.py | 37 +++++++++++++++++++++++++++++++---- spreg/tests/test_sp_panels.py | 31 +++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 12 deletions(-) mode change 100644 => 100755 spreg/regimes.py mode change 100644 => 100755 spreg/tests/test_sp_panels.py diff --git a/spreg/regimes.py b/spreg/regimes.py old mode 100644 new mode 100755 index 814cc91b..66dd67c2 --- a/spreg/regimes.py +++ b/spreg/regimes.py @@ -85,8 +85,8 @@ def __init__(self, reg): def _chow_run(kr, kf, kryd, nr, betas, vm): if betas.shape[0] != vm.shape[0]: if kf > 0: - betas = betas[0:vm.shape[0], :] - kf = kf - 1 + kf = kf - (betas.shape[0] - vm.shape[0]) + betas = betas[0:vm.shape[0], :] else: brange = [] for i in range(nr): diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py index e23a4062..c62d247d 100755 --- a/spreg/sp_panels.py +++ b/spreg/sp_panels.py @@ -175,7 +175,8 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): data to be passed in as numpy arrays, hence the user can read their data in using any method. - >>> db = libpysal.io.open(libpysal.examples.get_path('NAT.dbf'),'r') + >>> nat = libpysal.examples.load_example('NCOVR') + >>> db = libpysal.io.open(nat.get_path("NAT.dbf"),'r') Extract the HR (homicide rates) data in the 70's, 80's and 90's from the DBF file and make it the dependent variable for the regression. Note that the data can also @@ -228,6 +229,30 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): either request a printout of the results with the command print(reg.summary) or check out the individual attributes of GM_KKP: + >>> print(reg.summary) + REGRESSION + ---------- + SUMMARY OF OUTPUT: GM SPATIAL ERROR PANEL MODEL - RANDOM EFFECTS (KKP) + ---------------------------------------------------------------------- + Data set : unknown + Weights matrix : unknown + Dependent Variable : HR Number of Observations: 3085 + Mean dependent var : 6.4983 Number of Variables : 3 + S.D. dependent var : 6.9529 Degrees of Freedom : 3082 + Pseudo R-squared : 0.3248 + + ------------------------------------------------------------------------------------ + Variable Coefficient Std.Error z-Statistic Probability + ------------------------------------------------------------------------------------ + CONSTANT 6.4922156 0.1126713 57.6208645 0.0000000 + RD 3.6244575 0.0877475 41.3055526 0.0000000 + PS 1.3118778 0.0852516 15.3883054 0.0000000 + lambda 0.4177759 + sigma2_v 22.8190821 + sigma2_1 39.9099294 + ------------------------------------------------------------------------------------ + ================================ END OF REPORT ===================================== + >>> print(reg.name_x) ['CONSTANT', 'RD', 'PS', 'lambda', ' sigma2_v', 'sigma2_1'] @@ -264,17 +289,21 @@ def __init__(self, y, x, w, full_weights=False, self.regimes = regimes self.name_regimes = USER.set_name_ds(name_regimes) regimes_l = self._set_regimes(w, bigy.shape[0]) - print(x_constant.shape, len(regimes_l)) + self.name_x_r = self.name_x x_constant, self.name_x = REGI.Regimes_Frame.__init__(self, x_constant, regimes_l, constant_regi=False, cols2regi='all', names=self.name_x) - self.title += " WITH REGIMES" BaseGM_KKP.__init__(self, bigy, x_constant, w, full_weights=full_weights) self.name_ds = USER.set_name_ds(name_ds) self.name_y = USER.set_name_y(name_y) self.name_x.extend(['lambda',' sigma2_v', 'sigma2_1']) self.name_w = USER.set_name_w(name_w, w) - SUMMARY.GM_Panels(reg=self, w=w, vm=vm) + if regimes is not None: + self.kf += 3 + self.chow = REGI.Chow(self) + self.title += " WITH REGIMES" + regimes = True + SUMMARY.GM_Panels(reg=self, w=w, vm=vm, regimes=regimes) def _set_regimes(self,w,n_rows): self.constant_regi = 'many' diff --git a/spreg/tests/test_sp_panels.py b/spreg/tests/test_sp_panels.py old mode 100644 new mode 100755 index 1bae1f62..b9ac345f --- a/spreg/tests/test_sp_panels.py +++ b/spreg/tests/test_sp_panels.py @@ -8,17 +8,18 @@ class Test_GM_KKP(unittest.TestCase): def setUp(self): - self.db = libpysal.io.open(libpysal.examples.get_path('NAT.dbf'),'r') + nat = libpysal.examples.load_example('NCOVR') + self.db = libpysal.io.open(nat.get_path("NAT.dbf"),'r') self.w = libpysal.weights.Queen.from_shapefile(libpysal.examples.get_path("NAT.shp")) self.w.transform = 'r' - y_var0 = ['HR70','HR80','HR90'] - x_var0 = ['RD70','RD80','RD90','PS70','PS80','PS90'] - self.y = np.array([self.db.by_col(name) for name in y_var0]).T - self.x = np.array([self.db.by_col(name) for name in x_var0]).T + self.y_var0 = ['HR70','HR80','HR90'] + self.x_var0 = ['RD70','RD80','RD90','PS70','PS80','PS90'] + self.y = np.array([self.db.by_col(name) for name in self.y_var0]).T + self.x = np.array([self.db.by_col(name) for name in self.x_var0]).T def test_wide_ident(self): - reg = GM_KKP(self.y,self.x,self.w,full_weights=False,name_y=['HR70','HR80','HR90'], name_x=['RD70','RD80','RD90','PS70','PS80','PS90']) + reg = GM_KKP(self.y,self.x,self.w,full_weights=False,name_y=self.y_var0, name_x=self.x_var0) np.testing.assert_allclose(reg.betas,np.array([[ 6.49221562], [ 3.62445753], [ 1.31187779], @@ -61,6 +62,24 @@ def test_long_ident(self): [ 7.38157674e-05, 1.13099329e-03, 7.26783636e-03]]),RTOL) np.testing.assert_equal(reg.name_x, ['CONSTANT', 'RD', 'PS', 'lambda', ' sigma2_v', 'sigma2_1']) np.testing.assert_equal(reg.name_y, 'HR') + + def test_regimes(self): + regimes = self.db.by_col("SOUTH") + reg = GM_KKP(self.y,self.x,self.w,full_weights=False,regimes=regimes, + name_y=self.y_var0, name_x=self.x_var0) + np.testing.assert_allclose(reg.betas,np.array([[ 5.25856482], + [ 3.19249165], + [ 1.0056967 ], + [ 7.94560642], + [ 3.13931041], + [ 1.53700634], + [ 0.35979407], + [22.5650005 ], + [39.71516708]]),RTOL) + np.testing.assert_allclose(np.sqrt(reg.vm.diagonal()),np.array([0.158986, 0.157543, 0.104128, 0.165254, 0.117737, 0.136666]),RTOL) + np.testing.assert_equal(reg.name_x, ['0_CONSTANT', '0_RD', '0_PS', '1_CONSTANT', '1_RD', '1_PS', 'lambda', ' sigma2_v', 'sigma2_1']) + np.testing.assert_equal(reg.name_y, 'HR') + if __name__ == '__main__': unittest.main() From 5acff5dd280a1bd72dfa37b08d16b9e376ad8f4f Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Tue, 18 Feb 2020 13:46:16 -0600 Subject: [PATCH 11/16] Adding Chow tests to test_sp_panels.py. --- spreg/tests/test_sp_panels.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spreg/tests/test_sp_panels.py b/spreg/tests/test_sp_panels.py index b9ac345f..3fa1257d 100755 --- a/spreg/tests/test_sp_panels.py +++ b/spreg/tests/test_sp_panels.py @@ -79,6 +79,10 @@ def test_regimes(self): np.testing.assert_allclose(np.sqrt(reg.vm.diagonal()),np.array([0.158986, 0.157543, 0.104128, 0.165254, 0.117737, 0.136666]),RTOL) np.testing.assert_equal(reg.name_x, ['0_CONSTANT', '0_RD', '0_PS', '1_CONSTANT', '1_RD', '1_PS', 'lambda', ' sigma2_v', 'sigma2_1']) np.testing.assert_equal(reg.name_y, 'HR') + np.testing.assert_allclose(reg.chow.regi,np.array([[1.420430e+02, 9.516507e-33], + [7.311490e-02, 7.868543e-01], + [9.652492e+00, 1.890949e-03]]),RTOL) + np.testing.assert_allclose(reg.chow.joint[0],158.7225,RTOL) if __name__ == '__main__': unittest.main() From 51d96cf24061280aa073711ad3646e1ced12b3f6 Mon Sep 17 00:00:00 2001 From: Pedro Amaral Date: Thu, 20 Feb 2020 14:51:50 -0600 Subject: [PATCH 12/16] Attempt at fixing Travis errors. --- spreg/tests/test_error_sp_sparse.py | 15 ++++----------- spreg/tests/test_sur_error.py | 3 ++- 2 files changed, 6 insertions(+), 12 deletions(-) mode change 100644 => 100755 spreg/tests/test_error_sp_sparse.py mode change 100644 => 100755 spreg/tests/test_sur_error.py diff --git a/spreg/tests/test_error_sp_sparse.py b/spreg/tests/test_error_sp_sparse.py old mode 100644 new mode 100755 index 6cd3babd..0ca48d8c --- a/spreg/tests/test_error_sp_sparse.py +++ b/spreg/tests/test_error_sp_sparse.py @@ -253,11 +253,8 @@ def test_model(self): np.testing.assert_allclose(reg.mean_y,my,RTOL) sy = 18.466069465206047 np.testing.assert_allclose(reg.std_y,sy,RTOL) - vm = np.array([[ 522.43841148, -6.07256915, -1.91429117, -8.97133162], - [ -6.07256915, 0.23801287, 0.0470161 , 0.02809628], - [ -1.91429117, 0.0470161 , 0.03209242, 0.00314973], - [ -8.97133162, 0.02809628, 0.00314973, 0.21575363]]) - np.testing.assert_allclose(reg.vm,vm,RTOL) + vm = np.array([22.85691168, 0.48786563, 0.17914357, 0.46449287]) + np.testing.assert_allclose(np.sqrt(reg.vm.diagonal()),vm,RTOL) sig2 = 181.78650186468832 np.testing.assert_allclose(reg.sig2,sig2,RTOL) @@ -304,12 +301,8 @@ def test_model(self): np.testing.assert_allclose(reg.mean_y,my,RTOL) sy = 18.466069465206047 np.testing.assert_allclose(reg.std_y,sy,RTOL) - vm = np.array([[ 522.43841148, -6.07256915, -1.91429117, -8.97133162], - [ -6.07256915, 0.23801287, 0.0470161 , 0.02809628], - [ -1.91429117, 0.0470161 , 0.03209242, 0.00314973], - [ -8.97133162, 0.02809628, 0.00314973, 0.21575363]]) - #np.testing.assert_allclose(reg.vm,vm,RTOL) - np.testing.assert_allclose(reg.vm, vm, RTOL) + vm = np.array([22.85691168, 0.48786563, 0.17914357, 0.46449287]) + np.testing.assert_allclose(np.sqrt(reg.vm.diagonal()), vm, RTOL) sig2 = 181.78650186468832 np.testing.assert_allclose(reg.sig2,sig2,RTOL) pr2 = 0.3018280166937799 diff --git a/spreg/tests/test_sur_error.py b/spreg/tests/test_sur_error.py old mode 100644 new mode 100755 index f5167b7a..cf753aa9 --- a/spreg/tests/test_sur_error.py +++ b/spreg/tests/test_sur_error.py @@ -6,7 +6,8 @@ from ..sur_error import SURerrorML, SURerrorGM from .test_sur import dict_compare from libpysal.common import RTOL -ATOL = 1e-12 +from libpysal.common import ATOL + class Test_SUR_error(unittest.TestCase): From 0b767f6496dc63d885203d8a23ccd2f90e44be69 Mon Sep 17 00:00:00 2001 From: pedrovma Date: Mon, 24 Feb 2020 14:14:09 -0600 Subject: [PATCH 13/16] Updating documentation. --- spreg/sp_panels.py | 142 ++++++++++++++++++++++++++++++++------------- 1 file changed, 101 insertions(+), 41 deletions(-) diff --git a/spreg/sp_panels.py b/spreg/sp_panels.py index c62d247d..d2e4776a 100755 --- a/spreg/sp_panels.py +++ b/spreg/sp_panels.py @@ -28,10 +28,10 @@ class BaseGM_KKP(RegressionPropsY): ---------- y : array n*tx1 array for dependent variable - X : array + x : array Two dimensional array with n*t rows and one column for each independent (exogenous) variable - (note,must already include constant term) + (note: must already include constant term) w : spatial weights object Spatial weights matrix full_weights: boolean @@ -41,16 +41,6 @@ class BaseGM_KKP(RegressionPropsY): Attributes ---------- - n_eq : int - number of time periods - n : int - number of observations in each cross-section - bigy : dictionary - with vectors of dependent variable, one for - each time period - bigX : dictionary - with matrices of explanatory variables, - one for each time period betas : array kx1 array of estimated coefficients u : array @@ -59,17 +49,30 @@ class BaseGM_KKP(RegressionPropsY): nx1 array of spatially filtered residuals predy : array nx1 array of predicted y values - + n : integer + Number of observations + t : integer + Number of time periods + k : integer + Number of variables for which coefficients are estimated + (including the constant) + y : array + nx1 array for dependent variable + x : array + Two dimensional array with n rows and one column for each + independent (exogenous) variable, including the constant + vm : array + Variance covariance matrix (kxk) """ ''' - def __init__(self,bigy,bigX,w,full_weights=False): + def __init__(self,y,x,w,full_weights=False): # 1a. OLS --> \tilde{\delta} - ols = OLS.BaseOLS(y=bigy, x=bigX) + ols = OLS.BaseOLS(y=y, x=x) self.x, self.y, self.n, self.k, self.xtx = ols.x, ols.y, ols.n, ols.k, ols.xtx N = w.n - T = bigy.shape[0]//N + T = y.shape[0]//N moments,trace_w2 = _moments_kkp(w.sparse, ols.u, 0) lambda1,sig_v = optim_moments(moments, all_par=True) Tw = SP.kron(SP.identity(T),w.sparse) @@ -85,7 +88,7 @@ def __init__(self,bigy,bigX,w,full_weights=False): else: Tau = SP.identity(3) Xi = SP.kron(Xi_a,Tau) - moments_b,trace_w2 = _moments_kkp(w.sparse, ols.u, 1,trace_w2) + moments_b,_ = _moments_kkp(w.sparse, ols.u, 1,trace_w2) G = np.vstack((np.hstack((moments[0],np.zeros((3,1)))),moments_b[0])) moments6 = [G,np.vstack((moments[1],moments_b[1]))] lambda2,sig_vb,sig_1b = optim_moments(moments6, vcX=Xi.toarray(), all_par=True, start=[lambda1,sig_v,sig_1]) @@ -95,8 +98,8 @@ def __init__(self,bigy,bigX,w,full_weights=False): gls_w = SP.identity(N*T) - theta*Q1 #With omega - xs = gls_w.dot(get_spFilter(w, lambda2, bigX)) - ys = gls_w.dot(get_spFilter(w, lambda2, bigy)) + xs = gls_w.dot(get_spFilter(w, lambda2, x)) + ys = gls_w.dot(get_spFilter(w, lambda2, y)) ols_s = OLS.BaseOLS(y=ys, x=xs) self.predy = spdot(self.x, ols_s.betas) self.u = self.y - self.predy @@ -104,7 +107,7 @@ def __init__(self,bigy,bigX,w,full_weights=False): self.betas = np.vstack((ols_s.betas, lambda2, sig_vb, sig_1b)) self.e_filtered = self.u - lambda2 * SP.kron(SP.identity(T), w.sparse).dot(self.u) - self.n_eq, self.n = T, N + self.t, self.n = T, N self._cache = {} class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): @@ -117,7 +120,7 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): ---------- y : array n*tx1 or nxt array for dependent variable - X : array + x : array Two dimensional array with n*t rows and k columns for independent (exogenous) variable or n rows and k*t columns (note, must not include a constant term) @@ -127,6 +130,12 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): Considers different weights for each of the 6 moment conditions if True or only 2 sets of weights for the first 3 and the last 3 moment conditions if False (default) + regimes : list + List of n values with the mapping of each + observation to a regime. Assumed to be aligned with 'y'. + vm : boolean + If True, include variance-covariance matrix in summary + results name_y : string or list of strings Name of dependent variable for use in output name_x : list of strings @@ -135,19 +144,11 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): Name of weights matrix for use in output name_ds : string Name of dataset for use in output + name_regimes : string + Name of regime variable for use in the output Attributes ---------- - n_eq : int - number of time periods - n : int - number of observations in each cross-section - bigy : dictionary - with vectors of dependent variable, one for - each time period - bigX : dictionary - with matrices of explanatory variables, - one for each time period betas : array kx1 array of estimated coefficients u : array @@ -156,7 +157,38 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): nx1 array of spatially filtered residuals predy : array nx1 array of predicted y values - + n : integer + Number of observations + t : integer + Number of time periods + k : integer + Number of variables for which coefficients are estimated + (including the constant) + y : array + nx1 array for dependent variable + x : array + Two dimensional array with n rows and one column for each + independent (exogenous) variable, including the constant + vm : array + Variance covariance matrix (kxk) + chow : tuple + Contains 2 elements. 1: Pair of Wald statistic and p-value + for the setup of global regime stability. 2: array with Wald + statistic (col 0) and its p-value (col 1) for each beta that + varies across regimes. + Exists only if regimes is not None. + name_y : string + Name of dependent variable for use in output + name_x : list of strings + Names of independent variables for use in output + name_w : string + Name of weights matrix for use in output + name_ds : string + Name of dataset for use in output + name_regimes : string + Name of regime variable for use in the output + title : string + Name of the regression method used """ Examples @@ -244,12 +276,12 @@ class GM_KKP(BaseGM_KKP,REGI.Regimes_Frame): ------------------------------------------------------------------------------------ Variable Coefficient Std.Error z-Statistic Probability ------------------------------------------------------------------------------------ - CONSTANT 6.4922156 0.1126713 57.6208645 0.0000000 - RD 3.6244575 0.0877475 41.3055526 0.0000000 - PS 1.3118778 0.0852516 15.3883054 0.0000000 + CONSTANT 6.4922156 0.1126713 57.6208690 0.0000000 + RD 3.6244575 0.0877475 41.3055536 0.0000000 + PS 1.3118778 0.0852516 15.3883058 0.0000000 lambda 0.4177759 - sigma2_v 22.8190821 - sigma2_1 39.9099294 + sigma2_v 22.8190822 + sigma2_1 39.9099323 ------------------------------------------------------------------------------------ ================================ END OF REPORT ===================================== @@ -305,7 +337,7 @@ def __init__(self, y, x, w, full_weights=False, regimes = True SUMMARY.GM_Panels(reg=self, w=w, vm=vm, regimes=regimes) - def _set_regimes(self,w,n_rows): + def _set_regimes(self,w,n_rows): #Must add case for regime_err_sep = True self.constant_regi = 'many' self.cols2regi = 'all' self.regime_err_sep = False @@ -334,14 +366,17 @@ def _moments_kkp(ws, u, i, trace_w2=None): i : integer 0 if Q0, 1 if Q1 + trace_w2 : float + trace of WW. Computed in 1st step and saved for step 2. - Attributes - ---------- + Returns + ------- moments : list List of two arrays corresponding to the matrices 'G' and 'g', respectively. - + trace_w2 : float + trace of WW. Computed in 1st step and saved for step 2. ''' N = ws.shape[0] @@ -377,6 +412,17 @@ def _moments_kkp(ws, u, i, trace_w2=None): def _get_Tau(ws, trace_w2): + ''' + Computes Tau as in :cite:`KKP2007`. + ... + + Parameters + ---------- + ws : Sparse matrix + Spatial weights sparse matrix + trace_w2 : float + trace of WW. Computed in 1st step of _moments_kkp + ''' N = ws.shape[0] T12 = 2*trace_w2/N wtw = ws.T.dot(ws) @@ -391,6 +437,20 @@ def _get_Tau(ws, trace_w2): def _get_panel_data(y, x, w, name_y, name_x): ''' Performs some checks on the data structure and converts from wide to long if needed. + ... + + Parameters + ---------- + y : array + n*tx1 or nxt array for dependent variable + x : array + Two dimensional array with n*t rows and k columns for + independent (exogenous) variable or n rows and k*t columns + (note, must not include a constant term) + name_y : string or list of strings + Name of dependent variable for use in output + name_x : list of strings + Names of independent variables for use in output ''' if y.shape[0]/w.n != y.shape[0]//w.n: From b559008e53c8de462a097559358a7663cea90351 Mon Sep 17 00:00:00 2001 From: pedrovma Date: Tue, 25 Feb 2020 13:24:16 -0600 Subject: [PATCH 14/16] Bump --- spreg/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spreg/__init__.py b/spreg/__init__.py index 7fdb12cf..afbc3710 100644 --- a/spreg/__init__.py +++ b/spreg/__init__.py @@ -1,4 +1,3 @@ - __version__ = "1.1.1" from .ols import * from .diagnostics import * From 6b78b4a9c105fcc0745d2e8bdb9a310aa30b19a9 Mon Sep 17 00:00:00 2001 From: pedrovma Date: Tue, 25 Feb 2020 13:40:14 -0600 Subject: [PATCH 15/16] Fixing Travis. --- spreg/tests/test_sur_error.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spreg/tests/test_sur_error.py b/spreg/tests/test_sur_error.py index cf753aa9..a21a3037 100755 --- a/spreg/tests/test_sur_error.py +++ b/spreg/tests/test_sur_error.py @@ -6,8 +6,8 @@ from ..sur_error import SURerrorML, SURerrorGM from .test_sur import dict_compare from libpysal.common import RTOL -from libpysal.common import ATOL +ATOL = 0.0001 class Test_SUR_error(unittest.TestCase): @@ -141,12 +141,12 @@ def test_error_gm(self): #2 equations [ 1.34136264e-01, 8.27537784e+00, 1.28048921e-16], [ 4.03310502e-02, 1.20903229e+01, 1.18818750e-33]])},rtol=RTOL, atol=ATOL) np.testing.assert_allclose(reg.lamsur,np.array([[ 0.55099267], - [ 0.52364925]]),RTOL) + [ 0.52364925]]),RTOL, ATOL) np.testing.assert_allclose(reg.corr,np.array([[ 1. , 0.29038532], [ 0.29038532, 1. ]]),RTOL) - np.testing.assert_allclose(reg.surchow,[[ 5.5135078 , 1. , 0.01887016], - [ 1.77544155, 1. , 0.18271008], - [ 1.14089432, 1. , 0.28546343]],rtol=RTOL, atol=ATOL) + np.testing.assert_allclose(reg.surchow,np.array([[5.51329 , 1. , 0.018873], + [1.775379, 1. , 0.182718], + [1.1408 , 1. , 0.285483]]),rtol=RTOL, atol=ATOL) def test_error_3eq_gm(self): #Three equation example, unequal K y_var1 = ['HR60','HR70','HR80'] @@ -175,7 +175,7 @@ def test_error_3eq_gm(self): #Three equation example, unequal K [ 1.21987743e-001, 1.15202312e+001, 1.04330705e-030]])},rtol=RTOL, atol=ATOL) np.testing.assert_allclose(reg.lamsur,np.array([[ 0.40589647], [ 0.42900222], - [ 0.41682256]]),RTOL) + [ 0.41682256]]),RTOL, ATOL) np.testing.assert_allclose(reg.corr,np.array([[ 1. , 0.22987815, 0.13516187], [ 0.22987815, 1. , 0.2492023 ], [ 0.13516187, 0.2492023 , 1. ]]),RTOL) From 0b4c2cb98570652d449e74bd415620a817c2d23a Mon Sep 17 00:00:00 2001 From: pedrovma Date: Wed, 26 Feb 2020 15:26:50 -0600 Subject: [PATCH 16/16] Relaxing two-dimension requirement for y across functions. --- spreg/error_sp.py | 6 +++--- spreg/error_sp_het.py | 6 +++--- spreg/error_sp_het_regimes.py | 6 +++--- spreg/error_sp_hom.py | 6 +++--- spreg/error_sp_hom_regimes.py | 6 +++--- spreg/error_sp_regimes.py | 6 +++--- spreg/ml_error.py | 2 +- spreg/ml_error_regimes.py | 2 +- spreg/ml_lag.py | 2 +- spreg/ml_lag_regimes.py | 2 +- spreg/ols.py | 2 +- spreg/ols_regimes.py | 2 +- spreg/probit.py | 2 +- spreg/twosls.py | 2 +- spreg/twosls_regimes.py | 2 +- spreg/twosls_sp.py | 2 +- spreg/twosls_sp_regimes.py | 2 +- spreg/user_output.py | 12 ++++++------ 18 files changed, 35 insertions(+), 35 deletions(-) diff --git a/spreg/error_sp.py b/spreg/error_sp.py index 8f4f4d67..d8a65669 100644 --- a/spreg/error_sp.py +++ b/spreg/error_sp.py @@ -283,7 +283,7 @@ def __init__(self, y, x, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Error.__init__(self, y=y, x=x_constant, w=w.sparse) @@ -609,7 +609,7 @@ def __init__(self, y, x, yend, q, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Endog_Error.__init__( @@ -995,7 +995,7 @@ def __init__(self, y, x, yend=None, q=None, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) yend2, q2 = set_endog(y, x, w, yend, q, w_lags, lag_q) x_constant = USER.check_constant(x) diff --git a/spreg/error_sp_het.py b/spreg/error_sp_het.py index 5e213d90..2552b6be 100755 --- a/spreg/error_sp_het.py +++ b/spreg/error_sp_het.py @@ -338,7 +338,7 @@ def __init__(self, y, x, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Error_Het.__init__( @@ -751,7 +751,7 @@ def __init__(self, y, x, yend, q, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Endog_Error_Het.__init__(self, y=y, x=x_constant, yend=yend, @@ -1176,7 +1176,7 @@ def __init__(self, y, x, yend=None, q=None, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) yend2, q2 = set_endog(y, x, w, yend, q, w_lags, lag_q) x_constant = USER.check_constant(x) diff --git a/spreg/error_sp_het_regimes.py b/spreg/error_sp_het_regimes.py index 6ffd8c7e..141fc365 100644 --- a/spreg/error_sp_het_regimes.py +++ b/spreg/error_sp_het_regimes.py @@ -288,7 +288,7 @@ def __init__(self, y, x, regimes, w, max_iter=1, epsilon=0.00001, step1c=False, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -773,7 +773,7 @@ def __init__(self, y, x, yend, q, regimes, w, name_regimes=None, summ=True, add_lag=False): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -1346,7 +1346,7 @@ def __init__(self, y, x, regimes, yend=None, q=None, n = USER.check_arrays(y, x) self.step1c = step1c - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) name_x = USER.set_name_x(name_x, x, constant=True) self.name_y = USER.set_name_y(name_y) diff --git a/spreg/error_sp_hom.py b/spreg/error_sp_hom.py index d285895e..80f6fc01 100644 --- a/spreg/error_sp_hom.py +++ b/spreg/error_sp_hom.py @@ -344,7 +344,7 @@ def __init__(self, y, x, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Error_Hom.__init__(self, y=y, x=x_constant, w=w.sparse, A1=A1, @@ -749,7 +749,7 @@ def __init__(self, y, x, yend, q, w, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) BaseGM_Endog_Error_Hom.__init__( @@ -1172,7 +1172,7 @@ def __init__(self, y, x, yend=None, q=None, name_w=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) yend2, q2 = set_endog(y, x, w, yend, q, w_lags, lag_q) x_constant = USER.check_constant(x) diff --git a/spreg/error_sp_hom_regimes.py b/spreg/error_sp_hom_regimes.py index 628d1e34..65dcb348 100644 --- a/spreg/error_sp_hom_regimes.py +++ b/spreg/error_sp_hom_regimes.py @@ -303,7 +303,7 @@ def __init__(self, y, x, regimes, w, name_w=None, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -791,7 +791,7 @@ def __init__(self, y, x, yend, q, regimes, w, name_ds=None, name_regimes=None, summ=True, add_lag=False): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -1363,7 +1363,7 @@ def __init__(self, y, x, regimes, yend=None, q=None, name_w=None, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) name_x = USER.set_name_x(name_x, x, constant=True) self.name_y = USER.set_name_y(name_y) diff --git a/spreg/error_sp_regimes.py b/spreg/error_sp_regimes.py index 3271230c..80a7cd2c 100644 --- a/spreg/error_sp_regimes.py +++ b/spreg/error_sp_regimes.py @@ -281,7 +281,7 @@ def __init__(self, y, x, regimes, w, cores=False, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -705,7 +705,7 @@ def __init__(self, y, x, yend, q, regimes, w, cores=False, name_ds=None, name_regimes=None, summ=True, add_lag=False): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi @@ -1223,7 +1223,7 @@ def __init__(self, y, x, regimes, yend=None, q=None, name_w=None, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) name_x = USER.set_name_x(name_x, x, constant=True) self.name_y = USER.set_name_y(name_y) diff --git a/spreg/ml_error.py b/spreg/ml_error.py index b4416a60..5aae94ae 100644 --- a/spreg/ml_error.py +++ b/spreg/ml_error.py @@ -450,7 +450,7 @@ def __init__(self, y, x, w, method='full', epsilon=0.0000001, spat_diag=False, vm=False, name_y=None, name_x=None, name_w=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) method = method.upper() diff --git a/spreg/ml_error_regimes.py b/spreg/ml_error_regimes.py index db205cd9..abab7dcd 100644 --- a/spreg/ml_error_regimes.py +++ b/spreg/ml_error_regimes.py @@ -278,7 +278,7 @@ def __init__(self, y, x, regimes, w=None, constant_regi='many', name_w=None, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) self.constant_regi = constant_regi self.cols2regi = cols2regi diff --git a/spreg/ml_lag.py b/spreg/ml_lag.py index c1ecb7f7..0ac7795a 100644 --- a/spreg/ml_lag.py +++ b/spreg/ml_lag.py @@ -551,7 +551,7 @@ def __init__(self, y, x, w, method='full', epsilon=0.0000001, spat_diag=False, vm=False, name_y=None, name_x=None, name_w=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) x_constant = USER.check_constant(x) method = method.upper() diff --git a/spreg/ml_lag_regimes.py b/spreg/ml_lag_regimes.py index d2f11bd6..ffbf202f 100644 --- a/spreg/ml_lag_regimes.py +++ b/spreg/ml_lag_regimes.py @@ -296,7 +296,7 @@ def __init__(self, y, x, regimes, w=None, constant_regi='many', name_w=None, name_ds=None, name_regimes=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) USER.check_spat_diag(spat_diag, w) name_y = USER.set_name_y(name_y) diff --git a/spreg/ols.py b/spreg/ols.py index 12a8512c..538a8de0 100644 --- a/spreg/ols.py +++ b/spreg/ols.py @@ -427,7 +427,7 @@ def __init__(self, y, x, name_w=None, name_gwk=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y) USER.check_robust(robust, gwk) USER.check_spat_diag(spat_diag, w) diff --git a/spreg/ols_regimes.py b/spreg/ols_regimes.py index f411a00a..a45f6f27 100644 --- a/spreg/ols_regimes.py +++ b/spreg/ols_regimes.py @@ -353,7 +353,7 @@ def __init__(self, y, x, regimes, name_w=None, name_gwk=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y) USER.check_robust(robust, gwk) USER.check_spat_diag(spat_diag, w) diff --git a/spreg/probit.py b/spreg/probit.py index 84563d0f..03f77786 100644 --- a/spreg/probit.py +++ b/spreg/probit.py @@ -802,7 +802,7 @@ def __init__( spat_diag=False): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) if w != None: USER.check_weights(w, y) spat_diag = True diff --git a/spreg/twosls.py b/spreg/twosls.py index b7eb7639..5edbff2a 100644 --- a/spreg/twosls.py +++ b/spreg/twosls.py @@ -438,7 +438,7 @@ def __init__(self, y, x, yend, q, name_w=None, name_gwk=None, name_ds=None): n = USER.check_arrays(y, x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y) USER.check_robust(robust, gwk) USER.check_spat_diag(spat_diag, w) diff --git a/spreg/twosls_regimes.py b/spreg/twosls_regimes.py index 107195ad..d950c43f 100644 --- a/spreg/twosls_regimes.py +++ b/spreg/twosls_regimes.py @@ -279,7 +279,7 @@ def __init__(self, y, x, yend, q, regimes, name_w=None, name_gwk=None, name_ds=None, summ=True): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y) USER.check_robust(robust, gwk) USER.check_spat_diag(spat_diag, w) diff --git a/spreg/twosls_sp.py b/spreg/twosls_sp.py index e13e1f74..ebdd8ee1 100755 --- a/spreg/twosls_sp.py +++ b/spreg/twosls_sp.py @@ -465,7 +465,7 @@ def __init__(self, y, x, yend=None, q=None, name_w=None, name_gwk=None, name_ds=None): n = USER.check_arrays(x, yend, q) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) USER.check_robust(robust, gwk) x_constant = USER.check_constant(x) diff --git a/spreg/twosls_sp_regimes.py b/spreg/twosls_sp_regimes.py index 3761ef77..5a81f033 100644 --- a/spreg/twosls_sp_regimes.py +++ b/spreg/twosls_sp_regimes.py @@ -433,7 +433,7 @@ def __init__(self, y, x, regimes, yend=None, q=None, name_w=None, name_gwk=None, name_ds=None): n = USER.check_arrays(y, x) - USER.check_y(y, n) + y = USER.check_y(y, n) USER.check_weights(w, y, w_required=True) USER.check_robust(robust, gwk) USER.check_spat_diag(spat_diag, w) diff --git a/spreg/user_output.py b/spreg/user_output.py index 87813f44..7d8562b0 100755 --- a/spreg/user_output.py +++ b/spreg/user_output.py @@ -327,9 +327,9 @@ def check_arrays(*arrays): raise Exception("all input data must be either numpy arrays or sparse csr matrices") shape = i.shape if len(shape) > 2: - raise Exception("all input arrays must have exactly two dimensions") + raise Exception("all input arrays must have two dimensions") if len(shape) == 1: - raise Exception("all input arrays must have exactly two dimensions") + shape = (shape[0],1) if shape[0] < shape[1]: raise Exception("one or more input arrays have more columns than rows") if not spu.spisfinite(i): @@ -357,8 +357,8 @@ def check_y(y, n): Returns ------- - Returns : nothing - Nothing is returned + y : anything + Object passed by the user to a regression class Examples -------- @@ -372,7 +372,7 @@ def check_y(y, n): >>> y = np.array(db.by_col("CRIME")) >>> y = np.reshape(y, (49,1)) - >>> check_y(y, 49) + >>> y = check_y(y, 49) # should not raise an exception @@ -390,7 +390,7 @@ def check_y(y, n): raise Exception("y must be a single column array matching the length of other arrays") if shape != (n, 1): raise Exception("y must be a single column array matching the length of other arrays") - + return y def check_weights(w, y, w_required=False, time=False): """Check if the w parameter passed by the user is a libpysal.W object and