Here are functions for estimating the parameters of the Generalized Pareto distribution using Bayesian strategies. These methods are shown in Baseline Methods for the Parameter Estimation of the Generalized Pareto Distribution (https://doi.org/10.3390/e24020178).
Density (dGPD), distribution function (pGPD), quantile function (qGPD) and random generation (rGPD) for the Generalized Pareto distribution with shape parameter equal to xi and scale parameter equal to sigma.
dGPD <- function(x,xi=0,sigma=1){
s <- x/sigma
if(xi==0) out <- exp(-s)/sigma else
out <- (1+xi*s)^(-1/xi-1)/sigma
if(xi>=0) out <- out*as.numeric(s>=0) else
out <- out*as.numeric((s>=0)&&(s<=-1/xi))
out
}
pGPD <- function(q,xi=0,sigma=1,lower.tail=TRUE){
s <- q/sigma
if(xi==0) out <- 1-exp(-s) else
out <- 1-(1+xi*s)^(-1/xi)
if(xi>=0) out <- out*as.numeric(s>=0) else
out <- out*as.numeric((s>=0)&&(s<=-1/xi))
if(!lower.tail) out <- 1-out
out
}
qGPD <- function(p,xi=0,sigma=1,lower.tail=TRUE){
if(!lower.tail) p <- 1-p
if(xi==0) out <- -sigma*log(1-p) else
out <- -sigma/xi*(1+(1-p)^(-xi))
}
rGPD <- function(n=1,xi=0,sigma=1){
ifelse(xi==0,-sigma*log(runif(n)),
-sigma/xi*(1+runif(n)^(-xi)))
}
Arguments
Here are functions to estimate the parameters of the Generalized Pareto distribution. Firstly, using the Metropolis-Hastings algorithm, and secondly, employing the strategy called Informative Priors Baseline Distribution for different base distributions.
When the shape parameter is equalt to 0, the Generalized Pareto distribution becomes the exponential distribution. Therefore, Metropolis-Hastings algorithm is provided for both the exponential distribution (MHExp) and GPD with a non-zero shape parameter (MHGPDTail).
MHExp <- function(data,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
u <- as.numeric(quantile(data,p))
Xu <- data[data>u]-u
m <- length(Xu)
sigma <- 1/rgamma(ndraw,1+m,1+sum(Xu))
print(paste("Scale = ",mean(sigma),sep=" "))
list(threshold=u,
excess=Xu+u,
MCMC=list(scale=sigma))
}
MHGPDTail <- function(data,shape,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
u <- as.numeric(quantile(data,p))
Xu <- data[data>u]-u
m <- length(Xu)
if(shape=="light"){
MXu <- max(Xu)
k0 <- 0.15; delta0 <- sd(data)/k0
a1 <- 0.1; b1 <- 0.1; sdk <- 0.1
a2 <- 0.1; b2 <- 0.1; sddelta <- 0.1
ki <- k0; deltai <- delta0
for(i in 1:nburn){
kc <- rnorm(1,ki,sdk)
while(kc<0) kc <- rnorm(1,ki,sdk)
deltac <- rnorm(1,deltai,sddelta)
while(deltac<MXu) deltac <- rnorm(1,deltai,sddelta)
rk <- (a1-m-1)*log(kc/ki) + b1*(ki-kc) + (1/kc-1/ki)*sum(log(1-Xu/deltai))
rdelta <- (a2-m-1)*log(deltac/deltai) + b2*(deltai-deltac) +
(1/ki-1)*sum(log(1-Xu/deltac)) - (1/ki-1)*sum(log(1-Xu/deltai))
v <- log(runif(2))
if(v[1]<rk) ki <- kc
if(v[2]<rdelta) deltai <- deltac
}
draw <- matrix(c(-ki,ki*deltai),ncol=2,nrow=ndraw,byrow=TRUE)
for(i in 2:ndraw){
for(j in 1:nthin){
kc <- rnorm(1,ki,sdk)
while(kc<0) kc <- rnorm(1,ki,sdk)
deltac <- rnorm(1,deltai,sddelta)
while(deltac<MXu) deltac <- rnorm(1,deltai,sddelta)
rk <- (a1-m-1)*log(kc/ki) + b1*(ki-kc) + (1/kc-1/ki)*sum(log(1-Xu/deltai))
rdelta <- (a2-m-1)*log(deltac/deltai) + b2*(deltai-deltac) +
(1/ki-1)*sum(log(1-Xu/deltac)) - (1/ki-1)*sum(log(1-Xu/deltai))
v <- log(runif(2))
if(v[1]<rk) ki <- kc
if(v[2]<rdelta) deltai <- deltac
}
draw[i,] <- c(-ki,ki*deltai)
}
} else {
xi0 <- 1; sigma0 <- 100
alpha <- 10^(-6); cc <- 10^(-3); sdxi <- 0.1
a1 <- 0.1; b1 <- 0.1; sdsigma <- 5
xii <- xi0; sigmai <- sigma0
for(i in 1:nburn){
xic <- rnorm(1,xii,sdxi)
while(xic<cc) xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
while(sigmac<0) sigmac <- rnorm(1,sigmai,sdsigma)
rxi <- (alpha+1)*log(xii/xic) + (1+1/xii)*sum(log(1+xii*Xu/sigmai)) -
(1+1/xic)*sum(log(1+xic*Xu/sigmai))
rsigma <- (m+a1+1)*log(sigmai/sigmac) + b1*(1/sigmai-1/sigmac) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai)) - (1+1/xii)*sum(log(1+xii*Xu/sigmac))
v <- log(runif(2))
if(v[1]<rxi) xii <- xic
if(v[2]<rsigma) sigmai <- sigmac
}
draw <- matrix(c(xii,sigmai),ncol=2,nrow=ndraw,byrow=TRUE)
for(i in 2:ndraw){
for(j in 1:nthin){
xic <- rnorm(1,xii,sdxi)
while(xic<cc) xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
while(sigmac<0) sigmac <- rnorm(1,sigmai,sdsigma)
rxi <- (alpha+1)*log(xii/xic) + (1+1/xii)*sum(log(1+xii*Xu/sigmai)) -
(1+1/xic)*sum(log(1+xic*Xu/sigmai))
rsigma <- (m+a1+1)*log(sigmai/sigmac) + b1*(1/sigmai-1/sigmac) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai)) - (1+1/xii)*sum(log(1+xii*Xu/sigmac))
v <- log(runif(2))
if(v[1]<rxi) xii <- xic
if(v[2]<rsigma) sigmai <- sigmac
}
draw[i,] <- c(xii,sigmai)
}
}
print(paste("Shape = ",mean(draw[,1])," Scale = ",mean(draw[,2]),sep=" "))
list(threshold=u,
excess=Xu+u,
MCMC=list(shape=draw[,1],scale=draw[,2]))
}
MHGPD <- function(data,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
shape <- readline(prompt = "Indicate whether you want to estimate an exponential tail (exp), a light tail (light) or a heavy tail (heavy): ")
if(shape=="exp"){
MHExp(data,p,nthin,ndraw,nburn)
} else{
MHGPDTail(data,shape,p,nthin,ndraw,nburn)
}
}
Arguments
Value
Return a list object.
It displays on the screen the mean of the chain for each parameter.
Hence, Informative Priors Baseline Distribution algorithm is shown for different base distributions.
Stable distributions
IPBDMStable <- function(data,dist,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
n <- length(data)
u <- as.numeric(quantile(data,p))
Xu <- data[data>u] - u
m <- length(Xu)
dist <- readline(prompt = "Indicate whether you want to estimate an normal distribution (norm), Cauchy distribution (cauchy) or Lévy distribution (levy): ")
switch(dist,
"norm" = {
MXu <- max(Xu)
muxi0 <- -0.7 + 0.61*p; sdxi0 <- 0.03
musigma0 <- (0.34+3.18*(1-p)-12.4*(1-p)^2)*sd(data)
c1 <- -46.24; c2 <- 83.55; c3 <- -41.58
},
"cauchy" = {
muxi0 <- 1; sdxi0 <- 0.065
c1 <- 323.57; c2 <- -588.51; c3 <- 266.13
a <- 1; b <- 1
scalei <- as.numeric((quantile(data,3/4)-quantile(data,1/4))/2)
musigma0 <- 1/(pi*(1-p))*scalei
sdscale <- 0.1
},
"levy" = {
muxi0 <- 2; sdxi0 <- 0.1
c1 <- 500.2; c2 <- -900.9; c3 <- 408.2
scalei <- rgamma(1,1+n/2,1+sum(1/data)/2)
musigma0 <- 4/(pi*(1-p)^2)*scalei
}
)
sdsigma0 <- exp(c1*p^2+c2*p+c3)
sdxi <- 0.1; sdsigma <- 0.1
xii <- rnorm(1,muxi0,sdxi0)
sigmai <- rnorm(1,musigma0,sdsigma0)
if(dist=="norm"){
while(MXu>=(-sigmai/xii)||sigmai<=0||xii>=0){
xii <- rnorm(1,muxi0,sdxi0)
sigmai <- rnorm(1,musigma0,sdsigma0)
}
} else {
while(xii<0) xii <- rnorm(1,muxi0,sdxi0)
while(sigmai<=0) sigmai <- rnorm(1,musigma0,sdsigma0)
}
for(i in 1:nburn){
xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
if(dist=="norm"){
while(MXu>=(-sigmac/xic)||sigmac<=0||xic>=0){
xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
}
} else {
while(xic<0) xic <- rnorm(1,xii,sdxi)
while(sigmac<=0) sigmac <- rnorm(1,sigmai,sdsigma)
}
switch (dist,
"norm" = {
scale <- sqrt(1/rgamma(1,1+n/2,1+sum(data^2)/2))
musigma0 <- (0.34+3.18*(1-p)-12.4*(1-p)^2)*scale
},
"cauchy" = {
scale <- rnorm(1,scalei,sdscale)
while(scale<=0) scale <- rnorm(1,scalei,sdscale)
rscale <- (a-n-1)*log(scale/scalei) - b*(scale-scalei) -
sum(log(1+data^2/scale^2))+sum(log(1+data^2/scalei^2))
if(log(runif(1))<rscale) scalei <- scale
musigma0 <- 1/(pi*(1-p))*scalei
},
"levy" = {
scale <- rgamma(1,1+n/2,1+sum(1/data)/2)
musigma0 <- 4/(pi*(1-p)^2)*scale
}
)
if(dist=="norm"){
r <- m*log(sigmai/sigmac) + 0.5*((xii-muxi0)^2 - (xic-muxi0)^2)/sdxi0^2 +
0.5*((sigmai-musigma0)^2 - (sigmac-musigma0)^2)/sdsigma0^2 -
(1+1/xic)*sum(log(1+xic*Xu/sigmac)) + (1+1/xii)*sum(log(1+xii*Xu/sigmai))
if(log(runif(1))<r){
xii <- xic
sigmai <- sigmac
}
} else {
rxi <- 0.5*((xii-muxi0)^2 - (xic-muxi0)^2)/sdxi0^2 -
(1+1/xic)*sum(log(1+xic*Xu/sigmai)) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai))
rsigma <- m*log(sigmai/sigmac) + 0.5*(sigmai - musigma0)^2/sdsigma0^2 -
0.5*(sigmac-musigma0)^2/sdsigma0^2 -
(1+1/xii)*sum(log(1+xii*Xu/sigmac)) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai))
v <- log(runif(2))
if(v[1]<rxi) xii <- xic
if(v[2]<rsigma) sigmai <- sigmac
}
}
draw <- matrix(c(xii,sigmai),ncol=2,nrow=ndraw,byrow=TRUE)
for(i in 2:ndraw){
for(j in 1:nthin){
xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
if(dist=="norm"){
while(MXu>=(-sigmac/xic)||sigmac<=0||xic>=0){
xic <- rnorm(1,xii,sdxi)
sigmac <- rnorm(1,sigmai,sdsigma)
}
} else {
while(xic<0) xic <- rnorm(1,xii,sdxi)
while(sigmac<=0) sigmac <- rnorm(1,sigmai,sdsigma)
}
switch (dist,
"norm" = {
scale <- sqrt(1/rgamma(1,1+n/2,1+sum(data^2)/2))
musigma0 <- (0.34+3.18*(1-p)-12.4*(1-p)^2)*scale
},
"cauchy" = {
scale <- rnorm(1,scalei,sdscale)
while(scale<=0) scale <- rnorm(1,scalei,sdscale)
rscale <- (a-n-1)*log(scale/scalei) - b*(scale-scalei) -
sum(log(1+data^2/scale^2))+sum(log(1+data^2/scalei^2))
if(log(runif(1))<rscale) scalei <- scale
musigma0 <- 1/(pi*(1-p))*scalei
},
"levy" = {
scale <- rgamma(1,1+n/2,1+sum(1/data)/2)
musigma0 <- 4/(pi*(1-p)^2)*scale
}
)
if(dist=="norm"){
r <- m*log(sigmai/sigmac) + 0.5*((xii-muxi0)^2 - (xic-muxi0)^2)/sdxi0^2 +
0.5*((sigmai-musigma0)^2 - (sigmac-musigma0)^2)/sdsigma0^2 -
(1+1/xic)*sum(log(1+xic*Xu/sigmac)) + (1+1/xii)*sum(log(1+xii*Xu/sigmai))
if(log(runif(1))<r){
xii <- xic
sigmai <- sigmac
}
} else {
rxi <- 0.5*((xii-muxi0)^2 - (xic-muxi0)^2)/sdxi0^2 -
(1+1/xic)*sum(log(1+xic*Xu/sigmai)) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai))
rsigma <- m*log(sigmai/sigmac) + 0.5*(sigmai - musigma0)^2/sdsigma0^2 -
0.5*(sigmac-musigma0)^2/sdsigma0^2 -
(1+1/xii)*sum(log(1+xii*Xu/sigmac)) +
(1+1/xii)*sum(log(1+xii*Xu/sigmai))
v <- log(runif(2))
if(v[1]<rxi) xii <- xic
if(v[2]<rsigma) sigmai <- sigmac
}
}
draw[i,] <- c(xii,sigmai)
}
print(paste("Shape = ",mean(draw[,1])," Scale = ",mean(draw[,2]),sep=" "))
list(threshold=u,
excess=Xu+u,
MCMC=list(shape=draw[,1],scale=draw[,2]))
}
Exponential distribution
IPBDMExp <- function(data,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
n <- length(data)
u <- as.numeric(quantile(data,p))
Xu <- data[data>u] - u
m <- length(Xu)
sigmai <- mean(data)
for(i in 1:nburn){
lambdai <- rgamma(1,1+n,1+sum(data))
sigmac <- 1/lambdai
rsigma <- m*log(sigmai/sigmac) + sum(Xu)*(1/sigmai-1/sigmac)
if(log(runif(1))<rsigma) sigmai <- sigmac
}
draw <- sigmai
for(i in 2:ndraw){
for(j in 1:nthin){
lambdai <- rgamma(1,1+n,1+sum(data))
sigmac <- 1/lambdai
rsigma <- m*log(sigmai/sigmac) + sum(Xu)*(1/sigmai-1/sigmac)
if(log(runif(1))<rsigma) sigmai <- sigmac
}
draw <- c(draw,sigmai)
}
print(paste("Scale = ",mean(draw),sep=" "))
list(threshold=u,
excess=Xu+u,
MCMC=list(scale=draw))
}
Gamma distribution
IPBDMGamma <- function(data,p=0.9,nthin=25,ndraw=1000,nburn=1/3*ndraw){
n <- length(data)
u <- as.numeric(quantile(data,p))
Xu <- data[data>u] - u
m <- length(Xu)
alphai <- mean(data)^2/var(data); sdalpha <- 0.5
betai <- mean(data)/var(data); sdbeta <- 0.5
xii <- -0.032+0.014/alphai
sigmai <- 1/betai*(0.5+0.5*sqrt(alphai))
for(i in 1:nburn){
alphac <- rnorm(1,alphai,sdalpha)
betac <- rnorm(1,betai,sdbeta)
while(alphac<0||betac<0){
alphac <- rnorm(1,alphai,sdalpha)
betac <- rnorm(1,betai,sdbeta)
}
rB <- -n*log(gamma(alphac)) + (n*alphac-1)*log(betac) +
(alphac-1)*sum(log(data)) - betac*sum(data) +
0.5*log(alphac*trigamma(alphac)-1) +
n*log(gamma(alphai)) - (n*alphai-1)*log(betai) -
(alphai-1)*sum(log(data)) + betai*sum(data) -
0.5*log(alphai*trigamma(alphai)-1)
if(log(runif(1))<rB){
alphai <- alphac
betai <- betac
}
xic <- -0.032+0.014/alphai
sigmac <- 1/betai*(0.5+0.5*sqrt(alphai))
rIP <- -m*log(sigmac) - (1+1/xic)*sum(log(1+xic*Xu/sigmac)) +
m*log(sigmai) + (1+1/xii)*sum(log(1+xii*Xu/sigmai))
if(log(runif(1))<rIP){
xii <- xic
sigmai <- sigmac
}
}
draw <- matrix(c(xii,sigmai),ncol=2,nrow=ndraw,byrow=TRUE)
for(i in 2:ndraw){
for(j in 1:nthin){
alphac <- rnorm(1,alphai,sdalpha)
betac <- rnorm(1,betai,sdbeta)
while(alphac<0||betac<0){
alphac <- rnorm(1,alphai,sdalpha)
betac <- rnorm(1,betai,sdbeta)
}
rB <- -n*log(gamma(alphac)) + (n*alphac-1)*log(betac) +
(alphac-1)*sum(log(data)) - betac*sum(data) +
0.5*log(alphac*trigamma(alphac)-1) +
n*log(gamma(alphai)) - (n*alphai-1)*log(betai) -
(alphai-1)*sum(log(data)) + betai*sum(data) -
0.5*log(alphai*trigamma(alphai)-1)
if(log(runif(1))<rB){
alphai <- alphac
betai <- betac
}
xic <- -0.032+0.014/alphai
sigmac <- 1/betai*(0.5+0.5*sqrt(alphai))
rIP <- -m*log(sigmac) - (1+1/xic)*sum(log(1+xic*Xu/sigmac)) +
m*log(sigmai) + (1+1/xii)*sum(log(1+xii*Xu/sigmai))
if(log(runif(1))<rIP){
xii <- xic
sigmai <- sigmac
}
}
draw[i,] <- c(xii,sigmai)
}
print(paste("Shape = ",mean(draw[1,])," Scale = ",mean(draw[,2]),sep=" "))
list(threshold=u,
excess=Xu+u,
MCMC=list(shape=draw[,1],scale=draw[,2]))
}
Arguments
Value
Return a list object.
It displays on the screen the mean of the chain for each parameter.