Nothing
#' Simulation function for strategy estimation.
#' @useDynLib stratEst,.registration = TRUE
#' @importFrom Rcpp sourceCpp
#' @param data a \code{stratEst.data} object. Alternatively, the arguments \code{num.ids}, \code{num.games}, and \code{num.periods} can be used if no data is available.
#' @param strategies a list of strategies. Each element if the list must be an object of class \code{stratEst.strategy}.
#' @param shares a numeric vector of strategy shares. The order of the elements corresponds to the order in \code{strategies}. \code{NA} values are not allowed. Use a list of numeric vectors if data has more than one sample and shares are sample specific.
#' @param coefficients a matrix of regression coefficients. Column names correspond to the names of the strategies, row names to the names of the covariates.
#' @param covariate.mat a matrix with the covariates in columns. The column names of the matrix indicate the names of the covariates. The matrix must have as many rows as there are individuals.
#' @param num.ids an integer. The number of individuals. Default is 100.
#' @param num.games an integer. The number of games. Default is 5.
#' @param num.periods a vector of integers with as many elements \code{num.games}. The elements specify the number of periods in each game. Default (\code{NULL}) means 5 periods in each game.
#' @param fixed.assignment a logical value. If \code{FALSE} individuals use potentially different strategies in each each game. If \code{TRUE}, individuals use the same strategy in each game. Default is \code{FALSE}.
#' @param input.na a logical value. If \code{FALSE} an input value is randomly selected for the first period. Default is \code{FALSE}.
#' @param sample.id a character string indicating the name of the variable which identifies the samples in data. Individual observations must be nested in samples. Default is \code{NULL}.
#' @return A \code{stratEst.data} object. A data frame in the long format with the following variables:
#' \item{id}{the variable that identifies observations of the same individual.}
#' \item{game}{the variable that identifies observations of the same game.}
#' \item{period}{the period of the game.}
#' \item{choice}{the discrete choices.}
#' \item{input}{the inputs.}
#' \item{sample}{the sample of the individual.}
#' \item{strategy}{the strategy of the individual.}
#' @description The simulation function of the package.
#' @examples
#' ## Simulate data of two strategies for choices "left" and "right".
#' lr <- c("left","right")
#' pi <- runif(1)
#' pr <- c(1,0,0,1)
#' tr <- c(1,2,1,2)
#' mixed <- stratEst.strategy(choices = lr, inputs = lr, prob.choices = c(pi, 1 - pi))
#' pure <- stratEst.strategy(choices = lr, inputs = lr, prob.choices = pr, tr.inputs = tr)
#' gamma <- runif(1)/4
#' pure$tremble <- gamma
#' beta <- rnorm(1)
#' p <- 1/sum(1 + exp(beta))
#' sim.shares <- c(p, 1-p)
#' sim.strategies <- list("mixed" = mixed, "pure" = pure)
#' sim.data <- stratEst.simulate(strategies = sim.strategies, shares = sim.shares)
#'
#' @export
stratEst.simulate <- function( data = NULL, strategies, shares = NULL, coefficients = NULL, covariate.mat = NULL, num.ids = 100, num.games = 5, num.periods = NULL, fixed.assignment = TRUE, input.na = FALSE, sample.id = NULL ){
##################################################################################################
# CHECK INPUTS
##################################################################################################
# check strategies
if( missing(strategies) ) {
stop("stratEst error: Mandatory input object 'strategies' is missing. Specify an integer or create a data.frame object.")
}else{
stratEst.simulate.check.strategies.return <- stratEst.simulate.check.strategies( strategies )
strategies_matrix_list <- stratEst.simulate.check.strategies.return$strategies.matrix.list
num_samples_strategies <- length(strategies_matrix_list)
trembles_list <- stratEst.simulate.check.strategies.return$trembles.list
num_strats <- stratEst.simulate.check.strategies.return$num_strats
unique_inputs <- stratEst.simulate.check.strategies.return$unique.inputs
unique_outputs <- stratEst.simulate.check.strategies.return$unique.outputs
num_inputs <- stratEst.simulate.check.strategies.return$num.unique.inputs
num_outputs <- stratEst.simulate.check.strategies.return$num.unique.outputs
sid <- stratEst.simulate.check.strategies.return$sid
names_strategies <- stratEst.simulate.check.strategies.return$names.strategies
names_strategies_lcr <- stratEst.simulate.check.strategies.return$names.strategies
}
if( is.null( shares ) & ( is.null( coefficients ) | is.null( covariate.mat ) ) ){
stop("stratEst error: Either the input object 'shares' or the the inputs objects 'coefficients' and 'covariates' must be supplied.")
}
# check covariates
if( is.null(covariate.mat) ){
LCR = FALSE
}
else{
stratEst.simulate.check.covariates.return <- stratEst.simulate.check.covariates(covariate.mat)
covariate_mat <- stratEst.simulate.check.covariates.return$covariate.mat
num.ids <- stratEst.simulate.check.covariates.return$num.ids
num.covariates <- stratEst.simulate.check.covariates.return$num.covariates
names.covariates <- stratEst.simulate.check.covariates.return$names.covariates
LCR = TRUE
}
#check shares
if( is.null(shares) == FALSE ) {
stratEst.simulate.check.shares.return <- stratEst.simulate.check.shares( shares , LCR , num_strats )
shares = stratEst.simulate.check.shares.return$shares
num_samples_shares = stratEst.simulate.check.shares.return$num_samples
names_samples = stratEst.simulate.check.shares.return$names_samples
if( num_samples_shares > 1 ){
shares <- do.call(rbind,shares)
}else{
shares <- matrix(shares,1,length(shares))
}
}else{
num_samples_shares = 1
names_samples = "1"
}
#check coefficients
if( is.null(coefficients) ) {
if( LCR ){
stop("stratEst error: Input object 'coefficients' must be supplied.")
}
}else{
coefficient_mat <- stratEst.simulate.check.coefficients( coefficients , covariate_mat , num_strats , names_strategies_lcr )
if( LCR == FALSE ){
warning("stratEst warning: No covariates specified. The input object 'coefficients' is ignored.");
}
}
# check data
if( is.null( data ) == FALSE ){
if( "stratEst.data" %in% class(data) | "data.frame" %in% class(data) ){
if( is.null(covariate.mat) == FALSE & num.ids != length(unique(data$id)) ){
stop("stratEst error: The object 'covariate.mat' must have as many rows as there are unique ids in 'data'.")
}
num.ids <- length(unique(data$id))
sample_vec <- rep(1,nrow(data))
if( is.null(sample.id) == FALSE ){
if( sample.id %in% colnames(data)){
sample_vec <- data[,sample.id]
}
else{
stop(paste("stratEst error: The variable ",sample.id," cannot be found in the data.",sep=""))
}
}
unique.samples.data <- unique(sample_vec)
num.samples.data <- length(unique.samples.data)
if( num_samples_shares > 1 & num_samples_shares != num.samples.data ){
stop("stratEst error: Number of samples in 'data' and 'shares' must be the same.")
}
if( num_samples_strategies > 1 & num_samples_strategies != num.samples.data ){
stop("stratEst error: Number of samples in 'data' and 'strategies' must be the same.")
}
}else{
stop("stratEst error: Input object 'data' has to be of class 'stratEst.data'.")
}
stratEst.return.data <- stratEst.check.data( data )
id <- stratEst.return.data$id
game <- stratEst.return.data$game
period <- stratEst.return.data$period
input <- stratEst.return.data$input
output <- stratEst.return.data$output
input_factor <- stratEst.return.data$input.factor
output_factor <- stratEst.return.data$output.factor
levels_input <- stratEst.return.data$levels.input
levels_output <- stratEst.return.data$levels.output
}
if( is.null( data ) ){
# check num.ids
num.ids <- as.integer(num.ids)
if( "integer" %in% class(num.ids) == FALSE ){
stop("stratEst error: Input object 'num.ids' has to be of class 'integer'.")
}else{
if( num.ids < 0 ){
stop("stratEst error: Input object 'num.ids' cannot be negative.")
}
}
# check num.games
if( "numeric" %in% class(num.games) == FALSE ){
stop("stratEst error: Input object 'num.games' has to be of class 'numeric'.")
}else{
num.games <- round(num.games)
if( num.games < 0 ){
stop("stratEst error: Input object 'num.games' cannot be negative.")
}
}
# check num.periods
if( is.null( num.periods ) ){
num.periods <- rep(5,num.games)
}else{
if( "numeric" %in% class(num.periods) == FALSE ){
stop("stratEst error: Input object 'num.periods' has to be of class 'numeric'.")
}else{
if( length(num.periods) != num.games ){
stop("stratEst error: Input object 'num.periods' has to be a vector of length 'num.games'.")
}
num.periods <- round(num.periods)
if( any(num.periods < 0 ) ){
stop("stratEst error: Elements of the input object 'num.periods' cannot be negative.")
}
}
}
# check fixed.assignment
if( "logical" %in% class(fixed.assignment) == FALSE ){
stop("stratEst error: Input object 'fixed.assignment' has to be of class 'logical'.")
}
}
if( is.null( data ) ){
# balance num sample information
if( num_samples_strategies == num_samples_shares ){
num_samples = num_samples_strategies
}
else if( num_samples_strategies == 1 & num_samples_shares > 1 ){
num_samples = num_samples_shares
for( sam in 2:num_samples ){
strategies_matrix_list[[sam]] <- strategies_matrix_list[[1]]
trembles_list[[sam]] <- trembles_list[[1]]
}
}
else if( num_samples_strategies > 1 & num_samples_shares == 1 ){
num_samples = num_samples_strategies
shares <- t(matrix( shares , length(shares) , num_samples_strategies ))
}
else{
stop("stratEst error: The number of samples indicated in input object 'strategies' and 'shares' does not match.")
}
}else{
num_samples = length(unique(sample_vec))
# balance num sample information
if( num_samples_strategies == 1 & num_samples > 1 ){
for( sam in 2:num_samples ){
strategies_matrix_list[[sam]] <- strategies_matrix_list[[1]]
trembles_list[[sam]] <- trembles_list[[1]]
}
}
if( num_samples_shares == 1 & num_samples > 1 ){
shares <- t(matrix( shares , length(shares) , num_samples ))
}
if( ( num_samples_shares > 1 & num_samples_shares != num_samples ) ){
stop("stratEst error: The number of samples indicated in input object 'shares' does not match the number of samples in the data.")
}
if( ( num_samples_strategies > 1 & num_samples_strategies != num_samples ) ){
stop("stratEst error: The number of samples indicated in input object 'strategies' does not match the number of samples in the data.")
}
}
##################################################################################################
# GENERATE sim.data
##################################################################################################
# check fixed.assignment
if( is.null( data ) ){
sim.data <- NULL
max_id_sample <- 0
for( sam in 1:num_samples ){
strategies_matrix <- strategies_matrix_list[[sam]]
trembles <- trembles_list[[sam]]
trembles[is.na(trembles)] <- 0
trembles <- trembles
response_mat <- matrix(strategies_matrix[,2:(num_outputs+1)],nrow(strategies_matrix),num_outputs)
tremble_mat <- matrix(rep(trembles,ncol(response_mat)),nrow(response_mat),ncol(response_mat))
response_mat <- response_mat*(1-tremble_mat) + (1-response_mat)*tremble_mat/(ncol(response_mat)-1)
transition_mat <- matrix(strategies_matrix[,(num_outputs+2):(num_inputs+1+num_outputs)],nrow(strategies_matrix),num_inputs)
if( LCR ){
priors_individuals = exp( covariate_mat %*% coefficient_mat)/( apply(exp(covariate_mat %*% coefficient_mat),1,sum) )
}else{
priors_individuals = t( matrix( shares[sam,] , ncol(shares) , num.ids ) )
}
# assign ids to strategies (strategies assignmen mat)
strategy_assignment_mat <- matrix(NA,num.ids,num.games)
if( fixed.assignment ){
rand_vec = stats::runif(num.ids)
for( i in 1:num.ids){
assigned = FALSE
for( s in 1:num_strats ){
if( assigned == FALSE ){
if( rand_vec[i] <= sum( priors_individuals[i,(1:s)]) ){
strategy_assignment_mat[i,] <- rep( s , num.games )
assigned = TRUE
}
}
}
}
}else{
rand_mat = matrix(stats::runif(num.ids*num.games),num.ids,num.games)
for( i in 1:num.ids){
for( j in 1:num.games ){
assigned = FALSE
for( s in 1:num_strats ){
if( assigned == FALSE ){
if( rand_mat[i,j] <= sum( priors_individuals[i,(1:s)]) ){
strategy_assignment_mat[i,j] <- s
assigned = TRUE
}
}
}
}
}
}
# generate variables
if( fixed.assignment ){
id = max_id_sample + rep(c(1:num.ids),each=sum(num.periods))
}else{
id <- NULL
for( i in 1:num.games ){
id = max_id_sample + c(id,rep(c(((i-1)*num.ids + 1):((i-1)*num.ids + num.ids)),each=num.periods[i]))
}
}
game = rep( NA,num.ids*sum(num.periods) )
period = rep(NA,num.ids*sum(num.periods))
input = rep(0,num.ids*sum(num.periods))
output = rep(NA,num.ids*sum(num.periods))
sample = rep(names_samples[sam],num.ids*sum(num.periods))
strategy.id = rep(NA,num.ids*sum(num.periods))
if( LCR ){
covariate_vars = matrix(NA,num.ids*sum(num.periods),num.covariates)
}
# generate output
counter <- 1
for( i in 1:num.ids ){
for( g in 1:num.games ){
sid_sbj = strategy_assignment_mat[i,g]
indices_strat <- sid == sid_sbj
response_mat_sbj <- matrix(response_mat[ indices_strat , ],sum(indices_strat),ncol(response_mat))
response_mat_sbj <- abs(response_mat_sbj)
transition_mat_sbj <- matrix(transition_mat[ indices_strat , ],sum(indices_strat),ncol(transition_mat))
state <- 1
for( p in 1:num.periods[g] ){
strategy.id[counter] <- names_strategies[sid_sbj]
game[counter] <- g
period[counter] <- p
if( p > 1 | input.na == FALSE ){
input[counter] <- t(stats::rmultinom( 1 , 1 , rep(1,num_inputs)/num_inputs)) %*% c(1:num_inputs)
state <- transition_mat_sbj[state,input[counter]]
}
output[counter] = t(stats::rmultinom( 1 , 1 , response_mat_sbj[state,] )) %*% c(1:num_outputs)
if( LCR ){
covariate_vars[counter,] <- covariate_mat[i,]
}
counter <- counter + 1
}
}
}
strategy <- strategy.id
unique_output_values <- gsub("prob.", "", unique_outputs)
unique_input_values <- gsub("tr\\(", "", unique_inputs)
unique_input_values <- gsub("\\)", "", unique_input_values)
choice <- unique_output_values[output]
unique_input_values <- c(NA,unique_input_values)
input <- unique_input_values[input+1]
max_id_sample <- max(id)
if( LCR ){
sim.data_sample <- data.frame(id,game,period,choice,input,sample,strategy,covariate_vars)
}else{
sim.data_sample <- data.frame(id,game,period,choice,input,sample,strategy)
}
sim.data <- rbind(sim.data,sim.data_sample)
}
# define classes
sim.data$input <- as.factor(sim.data$input)
sim.data$choice <- as.factor(sim.data$choice)
sim.data$sample <- as.factor(sim.data$sample)
sim.data$id <- as.integer(sim.data$id)
sim.data$strategy <- as.factor(sim.data$strategy)
if( LCR ){
colnames(sim.data)[8:(8+num.covariates-1)] <- colnames(covariate.mat)
}
# make object of class stratEst.sim.data
attr(sim.data, "class") <- c("stratEst.data","data.frame")
}else{ # if data is not NULL
sim.data <- NULL
# generate variables
output = rep(NA,nrow(data))
sample = sample_vec
strategy.id = rep(NA,nrow(data))
if( LCR ){
covariate_vars = matrix(NA,nrow(data),num.covariates)
}
for( sam in 1:num_samples ){
unique.ids.sample <- unique(data$id[sample_vec==unique.samples.data[sam]])
num.ids.sample <- length(unique.ids.sample)
strategies_matrix <- strategies_matrix_list[[sam]]
trembles <- trembles_list[[sam]]
trembles[is.na(trembles)] <- 0
trembles <- trembles
response_mat <- matrix(strategies_matrix[,2:(num_outputs+1)],nrow(strategies_matrix),num_outputs)
tremble_mat <- matrix(rep(trembles,ncol(response_mat)),nrow(response_mat),ncol(response_mat))
response_mat <- response_mat*(1-tremble_mat) + (1-response_mat)*tremble_mat/(ncol(response_mat)-1)
transition_mat <- matrix(strategies_matrix[,(num_outputs+2):(num_inputs+1+num_outputs)],nrow(strategies_matrix),num_inputs)
if( LCR ){
priors_individuals = exp( covariate_mat %*% coefficient_mat)/( apply(exp(covariate_mat %*% coefficient_mat),1,sum) )
}else{
priors_individuals = t( matrix( shares[sam,] , ncol(shares) , num.ids.sample ) )
}
# assign ids to strategies (strategies assignmen mat)
strategy_assignment_vec <- rep(NA,num.ids.sample)
rand_vec = stats::runif(num.ids.sample)
for( i in 1:num.ids.sample){
assigned = FALSE
for( s in 1:num_strats ){
if( assigned == FALSE ){
if( rand_vec[i] <= sum( priors_individuals[i,(1:s)]) ){
strategy_assignment_vec[i] <- s
assigned = TRUE
}
}
}
}
# generate output
for( i in 1:num.ids.sample ){
unique.games <- unique(game[id==unique.ids.sample[i]])
num.games <- length(unique.games)
sid_sbj = strategy_assignment_vec[i]
indices_strat <- sid == sid_sbj
response_mat_sbj <- matrix(response_mat[ indices_strat , ],sum(indices_strat),ncol(response_mat))
response_mat_sbj <- abs(response_mat_sbj)
transition_mat_sbj <- matrix(transition_mat[ indices_strat , ],sum(indices_strat),ncol(transition_mat))
for( g in 1:num.games ){
unique.periods <- unique(period[id==unique.ids.sample[i] & game == unique.games[g]])
num.periods <- length(unique.periods)
state <- 1
for( p in 1:num.periods ){
index <- c(1:nrow(data))[id == unique.ids.sample[i] & game == unique.games[g] & period == unique.periods[p]]
strategy.id[index] <- names_strategies[sid_sbj]
if( input[index] > 0 ){
state <- transition_mat_sbj[state,input[index]]
}
output[index] = t(stats::rmultinom( 1 , 1 , response_mat_sbj[state,] )) %*% c(1:num_outputs)
if( LCR ){
covariate_vars[index,] <- covariate_mat[i,]
}
}
}
}
}
strategy <- strategy.id
unique_output_values <- gsub("prob.", "", unique_outputs)
unique_input_values <- gsub("tr\\(", "", unique_inputs)
unique_input_values <- gsub("\\)", "", unique_input_values)
choice <- unique_output_values[output]
sample <- unique.samples.data[sample]
unique_input_values <- c(NA,unique_input_values)
suppressWarnings(unique_input_values <- as.numeric(unique_input_values))
input <- unique_input_values[input+1]
if( LCR ){
sim.data <- data.frame(id,game,period,choice,input,sample,strategy,covariate_vars)
}else{
sim.data <- data.frame(id,game,period,choice,input,sample,strategy)
}
# define classes
sim.data$choice <- as.factor(sim.data$choice)
sim.data$sample <- as.factor(sim.data$sample)
sim.data$strategy <- as.factor(sim.data$strategy)
data$choice <- sim.data$choice
data$sample <- sim.data$sample
data$strategy <- sim.data$strategy
if(LCR){
num.cols.data <- ncol(data)
data <- cbind(data,sim.data[8:(8+num.covariates-1)])
colnames(data)[(num.cols.data+1):(num.cols.data+num.covariates)] <- colnames(covariate.mat)
}
sim.data <- data
# make object of class stratEst.sim.data
attr(sim.data, "class") <- c("stratEst.data","data.frame")
}
return(sim.data)
}
.onUnload <- function (libpath) { library.dynam.unload("stratEst", libpath)}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.