functions {
matrix obtain_adjustments(matrix W) {
real min_w;
real max_w;
int minmax_count;
matrix[2, cols(W)] adj;
adj[1, 1] = 0;
adj[2, 1] = 1;
if(cols(W) > 1) {
for(k in 2:cols(W)) { // remaining columns
min_w = min(W[1:rows(W), k]);
max_w = max(W[1:rows(W), k]);
minmax_count = 0;
for(j in 1:rows(W)){
minmax_count = minmax_count + W[j,k] == min_w || W[j,k] == max_w;
}
if(minmax_count == rows(W)) { // if column takes only 2 values
adj[1, k] = mean(W[1:rows(W), k]);
adj[2, k] = (max_w - min_w);
} else { // if column takes > 2 values
adj[1, k] = mean(W[1:rows(W), k]);
adj[2, k] = sd(W[1:rows(W), k]) * 2;
}
}
}
return adj;
}
}
data {
int<lower=1> I; // questions
int<lower=1> J; // persons
int<lower=1> N; // observations=J*I
int<lower=1, upper=I> ii[N]; // question for n
int<lower=1, upper=J> jj[N]; // person for n
int<lower=0, upper=1> y[N]; // correctness for n
int<lower=1> K; // person covariates
matrix[J,K] W; // person covariate matrix
}
transformed data {
matrix[2,K] adj; // values for centering and scaling covariates
matrix[J,K] W_adj; // centered and scaled covariates
adj = obtain_adjustments(W);
for(k in 1:K) {
for(j in 1:J){
W_adj[j,k] = (W[j,k] - adj[1,k]) / adj[2,k];
}
}
}
parameters {
vector[I-1] beta_free;//last item difficulty is given by previous items
vector[J] theta;
real<lower=0> sigma;
vector[K] lambda_adj;
}
transformed parameters {
vector[I] beta;
beta[1:(I-1)] = beta_free;
beta[I] = -1*sum(beta_free);
}
model { //parameters prior distributiuon and the model
target += normal_lpdf(beta | 0, 3);
theta ~ normal(W_adj*lambda_adj, sigma);//hierarchical centering
lambda_adj ~ student_t(3, 0, 1);
sigma ~ exponential(.1);
y ~ bernoulli_logit(theta[jj] - beta[ii]);
}
generated quantities {
vector[K] lambda;
lambda[2:K] = lambda_adj[2:K] ./ to_vector(adj[2,2:K]);
lambda[1] = W_adj[1, 1:K]*lambda_adj[1:K] - W[1, 2:K]*lambda[2:K];
}