Hi there,
I want to estimate a spatial lag panel data model with time-varying spatial autocorrelation parameters.
The model reads,
y_{it}=\rho_tWy_{it}+x_{it}\beta +\epsilon , \epsilon \sim N(0, \sigma^2)
I use the following rstan code, but I did not get the correct estimates. The fact is that \rho_t is always under-estimated.
I wonder Is there any way to improve my code? Or is there anything wrong in my code.
Many thanks
C.LING
functions {
matrix kronecker_prod(matrix A, matrix B) {
matrix[rows(A) * rows(B), cols(A) * cols(B)] C;
int m;
int n;
int p;
int q;
m = rows(A);
n = cols(A);
p = rows(B);
q = cols(B);
for (i in 1:m)
for (j in 1:n)
for (k in 1:p)
for (l in 1:q)
C[p*(i-1)+k,q*(j-1)+l] <- A[i,j]*B[k,l];
return C;
}
/* normal log-pdf for spatially lagged responses
* Args:
* y: the response vector
* mu: mean parameter vector
* sigma: residual standard deviation
* rho: a vector of autoregressive parameters
* W: spatial weight matrix
* Returns:
* a scalar to be added to the log posterior
*/
real normal_lagsar_lpdf(vector y, vector mu, real sigma,
vector rho, data matrix W) {
int NT = rows(y);
int N = rows(W);
int T = NT%/%N;
real inv_sigma2 = inv_square(sigma);
matrix[NT, NT] IW_tilde = add_diag(-kronecker_prod(diag_matrix(rho), W), 1);
vector[NT] half_pred;
real log_det;
half_pred = IW_tilde * y - mu;
log_det = log_determinant(IW_tilde);
return 0.5 * NT * log(inv_sigma2) + log_det -
0.5 * dot_self(half_pred) * inv_sigma2;
}
}
data {
int<lower=1> NT; // total number of observations
int<lower=1> T; // total number of periods
int<lower=1> N; // total number of observations in a cross-section
vector[NT] Y; // response variable
int<lower=1> K; // number of population-level effects
matrix[NT, K] X; // population-level design matrix
matrix[N, N] Msar; // spatial weight matrix
int prior_only; // should the likelihood be ignored?
}
transformed data {
int Kc = K - 1;
matrix[NT, Kc] Xc; // centered version of X without an intercept
vector[Kc] means_X; // column means of X before centering
for (i in 2:K) {
means_X[i - 1] = mean(X[, i]);
Xc[, i - 1] = X[, i] - means_X[i - 1];
}
}
parameters {
vector[Kc] b; // population-level effects
real Intercept; // temporary intercept for centered predictors
vector<lower=-1,upper=1>[T] lagsar; // lag-SAR correlation parameters
real<lower=0> sigma; // dispersion parameter
}
transformed parameters {
real lprior = 0; // prior contributions to the log posterior
lprior += student_t_lpdf(Intercept | 3, 34, 21.6);
lprior += student_t_lpdf(sigma | 3, 0, 21.6)
- 1 * student_t_lccdf(0 | 3, 0, 21.6);
}
model {
// likelihood including constants
if (!prior_only) {
// initialize linear predictor term
vector[NT] mu = rep_vector(0.0, NT);
mu += Intercept + Xc * b;
target += normal_lagsar_lpdf(Y | mu, sigma, lagsar, Msar);
}
// priors including constants
target += lprior;
}
generated quantities {
// actual population-level intercept
real b_Intercept = Intercept - dot_product(means_X, b);
}