Reputation: 69
I am new to R and am trying to vectorize an R script. However, my attempt at a vectorized version returns values of mean(SAg)
and sd(SAg)
(see below) that are different from those returned by the original script, even if I use the same RNG (random number generator) seed.
This is the original, non-vectorized code:
set.seed(42)
#n: tamanho da carteira (quantidade de segurados
tamanho = 10000
# prob_sin é a probabilidade esperada de ocorrência de sinistros com um segurado (1_i)
prob_sin = 0.02
# "cenarios" são as quantidades de simulações de atribuição de valor para o SAg
cenarios = 100
# sev_media é o valor esperado da indenização em caso de materialização do sinistro com a i-ésima apólice
sev_media = 10000
replicacoes_ind = matrix(NA, tamanho, cenarios) # 0 e 1
replicacoes_sev = matrix(NA, tamanho, cenarios) # se a matriz anterior tiver 1, então terá entrada diferente de zero
SAg = array(NA, cenarios)
# quant_sin é um vetor que armazena a quantidade de sinistros ocorridos em cada simulação/cenário
quant_sin = array(NA, cenarios)
for (j in 1:cenarios){ ### cria todos os cenários possíveis de ocorrência
for (i in 1:tamanho){ ### percorre toda a carteira
u <- runif(1,0,1) # gera um número aleatório entre 0 e 1
ifelse(u <= prob_sin, replicacoes_ind[i,j] <- 1, replicacoes_ind[i,j] <- 0)
ifelse(u <= prob_sin, replicacoes_sev[i,j] <- rexp(1,rate=1/sev_media), replicacoes_sev[i,j] <- 0)
}
quant_sin[j] <- sum(replicacoes_ind[,j])
SAg[j] <- sum(replicacoes_sev[,j])
}
mean(SAg); sd(SAg)
And this is my attempt at a vectorized implementation:
simulate_uniform = function(tamanho, cenarios){
return(matrix(data=runif(tamanho*cenarios, 0, 1), nrow=tamanho, ncol=cenarios))
}
fill_sev = function(p, u, dist, media, tamanho, cenarios){
# Matriz que armazena as indenizacoes ($) associadas a cada sinistro
matriz = matrix(NA, tamanho, cenarios)
# Indices aos quais houve sinistros
ind <- which(u <= p, arr.ind = TRUE)
# Usamos os indices acima para preencher as posicoes com a distribuicao escolhida
if(dist == "Exponencial"){
matriz[ind] = rexp(nrow(ind), rate = 1/media)
} else if(dist == "Uniforme"){
matriz[ind] = runif(nrow(ind), min = 0, max = 20000)
} else {
return(NULL)
}
# Para os indices restantes, substituimos por zero
matriz[is.na(matriz)] = 0
return(matriz)
}
set.seed(42)
cenarios = 100 # Numero de simulacoes
tamanho = 10000 # Carteira
prob_sin = 0.02 # Probabilidade de ocorrência de sinistros
sev_med = 10000 # Severidade média individual
distribuicao = "Exponencial" # Entre a distribuicao exponencial ou uniforme
SAg = array(NA, cenarios)
# Armazena a qtd de sinistros ocorridos em cada cenario
quant_sin = array(NA, cenarios)
u = simulate_uniform(tamanho, cenarios)
replicacoes_sev = fill_sev(prob_sin, u, distribuicao, sev_med, tamanho, cenarios)
if(is.null(replicacoes_sev)){
stop("Somente sao permitidas as ditribuicoes exponencial e uniforme.")
} else{
# Quantidade de sinistros em cada simulacao
quant_sin = colSums(replicacoes_sev != 0)
# Sinistro agregado em cada simulacao
SAg = colSums(replicacoes_sev)
# Media de SAg
mean(SAg)
# Desvio padrao de SAg
sd(SAg)
}
Can someone please point out what I am getting wrong?
Upvotes: 0
Views: 86
Reputation: 333
(This ought to be a comment only, but I'm lacking reputation for that)
I'm not entirely sure what's happening, but my guess is that the slight difference comes from the different order in which the (pseudo)random draws are used. In the vectorised code, R makes all the runif
draws first and then all the rexp
draws, in the non-vectorised version, it alternates between the two. Did you try to simulate it many times to rule out that one version structurally yields smaller mean/sd than the other version?
Upvotes: 2