#########################################################################################################
# Empirical Power simulation Codes of New Combined Threshold Unit Root Test introduced in
#
# "Threshold Unit Root Tests with Smooth Transitions"
#
# written by
#
# Dr. Mehmet ÖZCAN
# mehmetozcan@kmu.edu.tr
#
# *NOTES*
# 1)  Caner & Hansen (2001) Threshold Unit Root test and Threshold Effect test
#     programs are taken from Hansen's web page http://www.ssc.wisc.edu/~bhansen/ .
#     However, unit root test program are adjusted to test unit root null hypothesis
#     without any deterministic component.
#
# 2)  There are two indicator which come from Caner & Hansen (2001)'s codes. Caner &
#     Hansen investigate different type of threshol variable type and different trimming
#     intervals. In this study, lagged difference threshold variable and [0.15, 0.85]
#     trimming interval are used for all simulation experiments and empirical application.
#
#     thresh    Type of threshold variable
#  		  1 for long difference,   z(t-1)=y(t-1)-y(t-(m-1))
#  		  2 for lagged difference, z(t-1)=y(t-m)-y(t-m-1)
#  		  3 for lagged level,      z(t-1)=y(t-m)
#     trim      Trimming Range (normalized threshold, lambda)
#  		  1 for [.15,.85]
#  	 	  2 for [.10,.90]
#  		  3 for [.05,.95]
#
#    Other important imputs:
#     rep       Monte-Carlo replication
#     p         Autoregressive Lag Order
#     mmin      Minimal Delay Order for testing
#     mmax      Maximal Delay Order for testing
#     m		    Delay Order (fixed) for estimation. Set to 0 for m to be estimated by maximizing Wald RT statistics.
#
# 3) Results are printed to the screen.
#
# 4) All steps of simulation process are explained below. Please check them before run the codes.
#
# *Instructions*
#
# 1) First, please install required R packcages stated below.
# 2) You could simulate different parameter settings. Please check "simulation settings" part blow.
# 3) This codes includes critical values for T=100 and T=200.
# 4) Run all codes
#
#
#########################################################################################################
# Required Packcages
library(nloptr)
#########################################################################################################
# Required Functions
#########################################################################################################

#Power DGP
pwDGP <- function(n,m,p1,p2){
    n <- n+2
    et<- as.matrix(rnorm(n))
    et<- et-mean(et)

    yt <- matrix(0,n,1)
    for(i in 3:n) {
        if((yt[i-1]-yt[i-2])<0){yt[i]<--m+(1+p1)*yt[i-1]+et[i]}else{yt[i]<-m+(1+p2)*yt[i-1]+et[i]}
    }
    yt<-as.matrix(yt[3:n])
}

# LNV DGP
dgpLNV<-function(X, bA, bB, bC, vb){
tt<-length(vb)
X <-X[1:tt,]
staba<-function(b){(b[1]*X[,1]+b[2]*(1/(1+exp(-(b[3])*((X[,2])-b[4]*tt))))+vb)}
yAb<-staba(bA)

stabb<-function(b){(b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[4])*((X[,2])-b[5]*tt))))+vb)}
yBb<-stabb(bB)

stabc<-function(b){(b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt))))+
b[4]*(X[,2])*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt))))+vb)}
yCb<-stabc(bC)
list(yAb=yAb, yBb=yBb, yCb=yCb)
}

# Starting value estimation for LNV(1998) Models (A, B & C) #
startLNV<-function(dta){
tt<-length(dta)
tr<-as.matrix(c(1:tt))
cc<-as.matrix(rep(1,tt))

tauGs<-c()
for(kk in 1:tt){ tauGs[kk]<-(kk/tt) }
gamaGs<-seq(1,10,1)

SSRA<-matrix(0,length(tauGs),length(gamaGs))
SSRB<-matrix(0,length(tauGs),length(gamaGs))
SSRC<-matrix(0,length(tauGs),length(gamaGs))

for(vk in 1:3){
for(vi in 1:(length(gamaGs))){
for(vj in 1:(length(tauGs))){
st<-as.matrix((1/(1+exp(-(gamaGs[vi])*((tr)-(tauGs[vj]*tt))))))
if(vk==1){X<-as.matrix(cbind(cc,st))}
if(vk==2){X<-as.matrix(cbind(cc,tr,st))}
if(vk==3){X<-as.matrix(cbind(cc,tr,st,(tr*st)))}
XX<-(MASS:::ginv(t(X)%*%X, tol=1e-25))
betas<-XX%*%(t(X)%*%dta)
Yhat<-t((t(betas)%*%t(X)))
ehat<-(dta-Yhat)
if(vk==1){SSRA[vj,vi]<-sum((ehat)^2)}
if(vk==2){SSRB[vj,vi]<-sum((ehat)^2)}
if(vk==3){SSRC[vj,vi]<-sum((ehat)^2)}
}
}
}

for(vs in 1:3){
if(vs==1){posA<-which(SSRA == min(SSRA), arr.ind = TRUE);
st<-as.matrix((1/(1+exp(-(gamaGs[posA[2]])*((tr)-(tauGs[posA[1]]*tt))))));
X<-as.matrix(cbind(cc,st))}
if(vs==2){posB<-which(SSRB == min(SSRB), arr.ind = TRUE);
st<-as.matrix((1/(1+exp(-(gamaGs[posB[2]])*((tr)-(tauGs[posB[1]]*tt))))));
X<-as.matrix(cbind(cc,tr,st))}
if(vs==3){posC<-which(SSRC == min(SSRC), arr.ind = TRUE);
st<-as.matrix((1/(1+exp(-(gamaGs[posC[2]])*((tr)-(tauGs[posC[1]]*tt))))));
X<-as.matrix(cbind(cc,tr,st,(tr*st)))}

XX<-(MASS:::ginv(t(X)%*%X, tol=1e-25))

if(vs==1){betasA<-XX%*%(t(X)%*%dta);
betasA<-rbind(betasA,gamaGs[posA[2]],tauGs[posA[1]])}
if(vs==2){betasB<-XX%*%(t(X)%*%dta);
betasB<-rbind(betasB,gamaGs[posB[2]],tauGs[posB[1]])}
if(vs==3){betasC<-XX%*%(t(X)%*%dta);
betasC<-rbind(betasC,gamaGs[posC[2]],tauGs[posC[1]])}
}
list(betasA=betasA, betasB=betasB, betasC=betasC)
}

# LNV(1998) Models (A, B & C) Estimation with Sequential Quadratic Programing
estLNV<-function(yt, X, b0a, b0b, b0c){
tt<-length(yt)
stabA<-function(b){sum((yt-(b[1]*X[,1]+b[2]*(1/(1+exp(-(b[3])*((X[,2])-b[4]*tt))))))^2)}
stabB<-function(b){sum((yt-(b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[4])*((X[,2])-b[5]*tt))))))^2)}
stabC<-function(b){sum((yt-(b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt))))+
b[4]*(X[,2])*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt))))))^2)}

lba<-c(-Inf,-Inf,0,0)
uba<-c(Inf,Inf,Inf,1)

lbb<-c(-Inf,-Inf,-Inf,0,0)
ubb<-c(Inf,Inf,Inf,Inf,1)

lbc<-c(-Inf,-Inf,-Inf,-Inf,0,0)
ubc<-c(Inf,Inf,Inf,Inf,Inf,1)

SA<-nloptr:::slsqp(b0a,fn=stabA,lower=lba,upper=uba, control=list(xtol_rel=1e-25))
SB<-nloptr:::slsqp(b0b,fn=stabB,lower=lbb,upper=ubb, control=list(xtol_rel=1e-25))
SC<-nloptr:::slsqp(b0c,fn=stabC,lower=lbc,upper=ubc, control=list(xtol_rel=1e-25))

staba<-function(b){(b[1]*X[,1]+b[2]*(1/(1+exp(-(b[3])*((X[,2])-b[4]*tt)))))}
yhatA<-staba(SA$par)

stabb<-function(b){b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[4])*((X[,2])-b[5]*tt))))}
yhatB<-stabb(SB$par)

stabc<-function(b){(b[1]*X[,1]+b[2]*X[,2]+b[3]*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt))))+
b[4]*(X[,2])*(1/(1+exp(-(b[5])*((X[,2])-b[6]*tt)))))}
yhatC<-stabc(SC$par)

list(ehat=as.matrix(cbind((yt-yhatA),(yt-yhatB),(yt-yhatC))), yhat=as.matrix(cbind(yhatA,yhatB,yhatC)),BetaA=as.matrix(SA$par),BetaB=as.matrix(SB$par),BetaC=as.matrix(SC$par))
}

# ADF Estimator
linear<-function(dat,p,cons,trend){
    t <- nrow(dat)
    n <- t - 1 - p
    dy <- as.matrix(dat[2:t]-dat[1:(t-1)])
    y  <- as.matrix(dy[(1+p):(t-1)])
    x  <- cbind(dat[(1+p):(t-1)], dy[p:(t-2)])

    if(p>=2){for (k in 2:p) x <- cbind(x,dy[(p+1-k):(t-1-k)])}
    if(cons==1 & trend==0)  x <- cbind(rep(1,n), x)
    if(cons==1 & trend==1)  x <- cbind(rep(1,n),seq(1,n,1),x)

    kx     <- ncol(x)
    xx     <- solve(t(x)%*%x, tol=1e-25)
    bols   <- xx%*%(t(x)%*%y)
    eols   <- y - x%*%bols
    sols   <- t(eols)%*%eols
    sigols <- sols/(n-kx)
    seols  <- sqrt(diag(xx)%*%sigols)
    rho    <- bols[1+cons+trend]
    tadf   <- rho/seols[1+cons+trend]
    ar0    <- as.matrix(bols[(cons+trend+2):(cons+trend+1+p)])
    bic<-log((sum(eols^2))/t)+(length(bols)*(log(t)/t))
    aic<-log((sum(eols^2))/t)+(length(bols)*(2/t))
    list(ar0=ar0,eols=eols,aic=aic,bic=bic,tadf=tadf,rho=rho)
}

# Caner & Hansen (2001) Estimator
tur_est2 <- function(dat,p,mmin,mmax,m,constant,trend){
  t <- nrow(dat)
  n <- t - 1 - p
  mn <- mmax-mmin+1
  ms <- as.matrix(seq(mmin,mn,1))
  dy <- as.matrix(dat[2:t]-dat[1:(t-1)])
  y <- as.matrix(dy[(1+p):(t-1)])
  if(constant==1) x <- matrix(1,n,1)
  if (trend==1) x <- cbind(x,as.matrix(seq(1,n,1)))
  if(constant==1){x <- cbind(x,dat[(1+p):(t-1)],dy[p:(t-2)])}else{
  x <- cbind(dat[(1+p):(t-1)],dy[p:(t-2)])}
  if(p>1) for (ki in 2:p) x <- cbind(x,dy[(p+1-ki):(t-1-ki)])

  if (sum(coef)==0){
      xi_ns <- as.matrix(seq(1,p,1)+1+constant+trend)
        }else{
      idex <- colSums(as.matrix(coef%*%matrix(1,1,p))==(matrix(1,nrow(coef),1)%*%seq(1,p,1)))
      xi_ns <- seq(1,p,1)
      xi_ns <- as.matrix(xi_ns[idex==0]+1+constant+trend)
    }

  if (trend==0){
        if(constant==0){
	        if (sum(coef)==0){
            xi_s <- rbind(1)
                }else{xi_s <- rbind(1,(coef+1))
            }
        }
    }
  if (trend==0){
    if(constant==1){
	if (sum(coef)==0){
      xi_s <- rbind(1,2)
    }else{
      xi_s <- rbind(1,2,(coef+2))
    }
  }
  }
  if (trend==1){
    if(constant==1){
	if (sum(coef)==0){
      xi_s <- rbind(1,2,3)
    }else{
      xi_s <- rbind(1,2,3,(coef+3))
    }
  }
  }

  xs <- as.matrix(x[,xi_s])
  xns <- as.matrix(x[,xi_ns])

  if (thresh==1){
      qs <- dat[(1+p):(t-1)]-dat[(1+p-mmin):(t-1-mmin)]
      qs <- as.matrix(qs)
      if(p>1){
	  for (mi in (mmin+1):mmax){
          qs <- cbind(qs,(dat[(1+p):(t-1)]-dat[(1+p-mi):(t-1-mi)]))
      }
	  }
  }
  if (thresh==2){
      qs <- dat[(1+p-mmin+1):(t-1-mmin+1)]-dat[(1+p-mmin):(t-1-mmin)]
      qs <- as.matrix(qs)
      if(p>1){
	  for (mi in (mmin+1):mmax){
          qs <- cbind(qs,(dat[(1+p-mi+1):(t-1-mi+1)]-dat[(1+p-mi):(t-1-mi)]))
      }
	  }
  }
  if (thresh==3){
      qs <- dat[(1+p-mmin+1):(t-mmin)]
      qs <- as.matrix(qs)
      if(p>1){
	  for (mi in (mmin+1):mmax){
          qs <- cbind(qs,(dat[(1+p-mi+1):(t-mi)]))
      }
	  }
  }
  kx    <- ncol(x)
  ks    <- nrow(coef)+1+constant+trend
  xx    <- solve(t(x)%*%x, tol=1e-25)
  bols  <- xx%*%(t(x)%*%y)
  eols  <- y - x%*%bols
  sols  <- t(eols)%*%eols
  wwss  <- matrix(0,mn,1)
  smins <- matrix(0,mn,1)
  lams  <- matrix(0,mn,1)
  ws    <- matrix(0,mn,1)
  r1    <- matrix(0,mn,1)
  r2    <- matrix(0,mn,1)
  t1    <- matrix(0,mn,1)
  t2    <- matrix(0,mn,1)
  rur <- rbind(1,(ks+1))+trend+constant
  indx <- 1:(n)
  pi1 <-.2-.05*trim
  pi2 <-.8+.05*trim
  for (mi in 1:mn){
    q <- qs[,mi]
    qq <- unique(q)
    qq <- as.matrix(sort(qq))
    qq <- as.matrix(qq[(floor(n*pi1)+1):(ceiling(n*pi2)-1)])
    qn <- nrow(qq)
    s  <- matrix(0,qn,1)
    wws<- matrix(0,qn,1)
    for (qi in 1:qn){
      d1      <- as.matrix((q<qq[qi]))
      d2      <- 1-d1
      xz      <- cbind((xs*(d1%*%matrix(1,1,ncol(xs)))),(xs*(d2%*%matrix(1,1,ncol(xs)))),xns)
      xxi     <- solve(t(xz)%*%xz, tol=1e-25)
      bthresh <- xxi%*%(t(xz)%*%y)
      e       <- y-xz%*%bthresh
      s[qi]   <- t(e)%*%e
      v       <- xxi*as.vector((t(e)%*%e)/(n-kx-ks))
      vd      <- diag(v)
      ts      <- as.matrix(bthresh[rur]/sqrt(vd[rur]))
      wws[qi] <- t(ts)%*%ts
    }
    qi         <- which.max(wws)
    lam        <- qq[qi]
    smin       <- s[qi]
    wwsmax     <- wws[qi]
    ws[mi]     <- (n-kx-ks)*(sols-smin)/smin
    smins[mi]  <- smin
    lams[mi]   <- lam
    wwss[mi]   <- wwsmax
    d1         <- as.matrix((q<lam))
    d2         <- 1-d1
    xz         <- cbind((xs*(d1%*%matrix(1,1,ncol(xs)))),(xs*(d2%*%matrix(1,1,ncol(xs)))),xns)
    mmi        <- solve(t(xz)%*%xz, tol=1e-25)
    bthresh    <- mmi%*%(t(xz)%*%y)
    e          <- y - xz%*%bthresh
    v          <- mmi*as.vector((t(e)%*%e)/(n-kx-ks))
    vd         <- diag(v)
    ts         <- as.matrix(bthresh[rur]/sqrt(vd[rur]))
    r1[mi]     <- t(ts^2)%*%(ts<0)
    r2[mi]     <- t(ts)%*%ts
    t1[mi]     <- -ts[1]
    t2[mi]     <- -ts[2]
  }
  if (m != 0) {mi <- m-mmin+1}else{mi<- which.max(wwss)}
  mhat     <- ms[mi]
  w        <- ws[mi]
  lam      <- lams[mi]
  q        <- qs[,mi]
  d1       <- as.matrix((q<lam))
  d2       <- 1-d1
  xz       <- cbind((xs*(d1%*%matrix(1,1,ncol(xs)))),(xs*(d2%*%matrix(1,1,ncol(xs)))),xns)
  mmi      <- solve(t(xz)%*%xz, tol=1e-25)
  bthresh  <- mmi%*%(t(xz)%*%y)
  e        <- y - xz%*%bthresh
  ee       <- t(e)%*%e
  v        <- mmi*as.vector((ee)/(n-kx-ks))
  vd       <- diag(v)
  v1       <- vd[1:ks]
  v2       <- vd[(ks+1):(2*ks)]
  b1       <- bthresh[1:ks]
  b2       <- bthresh[(ks+1):(2*ks)]
  ts       <- as.matrix(((b1-b2)^2)/(v1+v2))
  bs_s     <- cbind(b1,sqrt(v1),matrix(0,ks,1),b2,sqrt(v2))
  bs_ns    <- cbind(bthresh[(1+2*ks):(kx+ks)],sqrt(vd[(1+2*ks):(kx+ks)]))
  ar01     <-bthresh[(2+constant+trend):(ks)]
  ar02     <-bthresh[(2+constant+trend+ks):(ks*2)]
  leng     <-sum(x[,ncol(x)]>lam)
list(mhat=mhat,lam=lam,e=e,bs_s=bs_s,ar01=ar01,ar02=ar02,b1=b1,b2=b2,r1=r1,r2=r2,t1=t1,t2=t2,ts=ts,ws=ws,w=w,
wws=wws, wwss=wwss,leng=leng,vd=vd)
}

###########################################################
# Caner & Hansen (2001) TAR Model Estimation Settings #####
thresh   <- 2
trim     <- 1
p        <- 1
m        <- 0
mmin     <- 1
mmax     <- p
coef     <- matrix(c(1:p),p,1)
###########################################################
# Simulation Settings: ####################################
rep      <- 10000
n        <- 100
# Fixed Parameters: #######################################
p2       <- c(-0.1 , -0.3, -0.9)
# Smooth Transtion Model A Parameters: ####################
LNVA_1 <- matrix(c(1, 2,  0.5, 0.5),         4,1)
LNVA_2 <- matrix(c(1, 2,  5  , 0.5),         4,1)
LNVA_3 <- matrix(c(1, 10, 0.5, 0.5),         4,1)
LNVA_4 <- matrix(c(1, 10, 5  , 0.5),         4,1)
# Smooth Transtion Model B Parameters: ####################
LNVB_1 <- matrix(c(1, 0.5, 2,  0.5 ,0.5),    5,1)
LNVB_2 <- matrix(c(1, 0.5, 2,  5   ,0.5),    5,1)
LNVB_3 <- matrix(c(1, 0.5, 10, 0.5 ,0.5),    5,1)
LNVB_4 <- matrix(c(1, 0.5, 10, 5   ,0.5),    5,1)
# Smooth Transtion Model C Parameters: ####################
LNVC_1 <- matrix(c(1, 0.5, 2,  0.5,  0.5, 0.5), 6,1)
LNVC_2 <- matrix(c(1, 0.5, 2,  0.5,  5  , 0.5), 6,1)
LNVC_3 <- matrix(c(1, 0.5, 10, 0.5,  0.5, 0.5), 6,1)
LNVC_4 <- matrix(c(1, 0.5, 10, 0.5,  5  , 0.5), 6,1)
# Smooth Transiton Model Parameter Cases: #################
lnvcase  <- 4
# TAR Parameter Cases: ####################################
#p1       <-c(-0.1, -0.3, -0.9)    # Case-1
p1       <-c(0, 0, 0)               # Case-2
#p1       <-c(-0.1, -0.1, -0.1)   # Case-3
###########################################################
# 5% Criticals T=100 ######################################
 R1A <- 21.15948
 R2A <- 21.27445
 R1B <- 27.69705
 R2B <- 27.77254
 R1C <- 30.93129
 R2C <- 30.95712
 LNVa<- -4.232 # LNV(1998) Critical Values from Table I
 LNVb<- -4.771
 LNVc<- -5.011
# 5% Criticals T=200 ######################################
#R1A <- 20.82907
#R2A <- 21.07073
#R1B <- 26.67934
#R2B <- 26.80033
#R1C <- 29.65022
#R2C <- 29.69269
#LNVa<- -4.161 # LNV(1998) Critical Values from Table I
#LNVb<- -4.629
#LNVc<- -4.867
###########################################################
# Simulation Process

tr<-as.matrix(c(1:n))
cc<-as.matrix(rep(1,n))

Apwr1<-matrix(0,3,1); Apwr2<-matrix(0,3,1);
Bpwr1<-matrix(0,3,1); Bpwr2<-matrix(0,3,1);
Cpwr1<-matrix(0,3,1); Cpwr2<-matrix(0,3,1);
lnvA <-matrix(0,3,1); lnvB <-matrix(0,3,1);
lnvC <-matrix(0,3,1);

set.seed(012345)
ptm <- proc.time()

if(lnvcase==1){ bA<-LNVA_1; bB<-LNVB_1; bC<-LNVC_1}
if(lnvcase==2){ bA<-LNVA_2; bB<-LNVB_2; bC<-LNVC_2}
if(lnvcase==3){ bA<-LNVA_3; bB<-LNVB_3; bC<-LNVC_3}
if(lnvcase==4){ bA<-LNVA_4; bB<-LNVB_4; bC<-LNVC_4}

for(h in 1:length(p2)){
Aszr1<- matrix(0,rep,1); Aszr2<- matrix(0,rep,1);
Bszr1<- matrix(0,rep,1); Bszr2<- matrix(0,rep,1);
Cszr1<- matrix(0,rep,1); Cszr2<- matrix(0,rep,1);
lnvAs<- matrix(0,rep,1); lnvBs<- matrix(0,rep,1);
lnvCs<- matrix(0,rep,1);

for(i in 1:rep){
X   <-as.matrix(cbind(cc,tr))
vb  <-as.matrix(pwDGP(n, 0, p1[h], p2[h]))
dat <-dgpLNV(X, bA, bB, bC, vb)

SLNVA<- startLNV(dat$yAb)
SLNVB<- startLNV(dat$yBb)
SLNVC<- startLNV(dat$yCb)
b0a  <- SLNVA$betasA
b0b  <- SLNVB$betasB
b0c  <- SLNVC$betasC

ELNVA<-estLNV(dat$yAb, X, b0a, b0b, b0c)
ELNVB<-estLNV(dat$yBb, X, b0a, b0b, b0c)
ELNVC<-estLNV(dat$yCb, X, b0a, b0b, b0c)

DA<-as.matrix(ELNVA$ehat)
DB<-as.matrix(ELNVB$ehat)
DC<-as.matrix(ELNVC$ehat)

tarA <-tur_est2(as.matrix(DA[,1]),p,mmin,mmax,m,0,0)
tarB <-tur_est2(as.matrix(DB[,2]),p,mmin,mmax,m,0,0)
tarC <-tur_est2(as.matrix(DC[,3]),p,mmin,mmax,m,0,0)
larA <-linear(as.matrix(DA[,1]),1,0,0)
larB <-linear(as.matrix(DB[,2]),1,0,0)
larC <-linear(as.matrix(DC[,3]),1,0,0)

if(tarA$r1[tarA$mhat]<R1A) Aszr1[i]<-1
if(tarA$r2[tarA$mhat]<R2A) Aszr2[i]<-1
if(tarB$r1[tarB$mhat]<R1B) Bszr1[i]<-1
if(tarB$r2[tarB$mhat]<R2B) Bszr2[i]<-1
if(tarC$r1[tarC$mhat]<R1C) Cszr1[i]<-1
if(tarC$r2[tarC$mhat]<R2C) Cszr2[i]<-1

if(abs(larA$tadf)<abs(LNVa)) lnvAs[i]<-1
if(abs(larB$tadf)<abs(LNVb)) lnvBs[i]<-1
if(abs(larC$tadf)<abs(LNVc)) lnvCs[i]<-1
}
Apwr1[h,] <- (100-((sum(Aszr1)*100)/rep))
Apwr2[h,] <- (100-((sum(Aszr2)*100)/rep))
Bpwr1[h,] <- (100-((sum(Bszr1)*100)/rep))
Bpwr2[h,] <- (100-((sum(Bszr2)*100)/rep))
Cpwr1[h,] <- (100-((sum(Cszr1)*100)/rep))
Cpwr2[h,] <- (100-((sum(Cszr2)*100)/rep))

lnvA[h,] <- (100-((sum(lnvAs)*100)/rep))
lnvB[h,] <- (100-((sum(lnvBs)*100)/rep))
lnvC[h,] <- (100-((sum(lnvCs)*100)/rep))
}

proc.time() - ptm
# Ozcan (2021)
CP  <- cbind(Apwr1,Bpwr1,Cpwr1,Apwr2,Bpwr2,Cpwr2)
# LNV (1998)
CPL <- cbind(lnvA, lnvB, lnvC)

printres <- function(CP,CPL){
CP <-format(CP, nsmall=2)
CPL<-format(CPL,nsmall=2)
if(lnvcase==1) dg<-c(2 ,0.5)
if(lnvcase==2) dg<-c(2 ,  5)
if(lnvcase==3) dg<-c(10,0.5)
if(lnvcase==4) dg<-c(10,  5)
cat ("\n")
cat ("Empirical Power Values for Selected Case              "                             , "\n")
cat ("\n")
cat ("Number of Observations (T):", n                                                     , "\n")
cat ("               Replication:", rep                                                   , "\n")
cat ("              Nominal Size:", "%5"                                                  , "\n")
cat ("\n")
cat ("Model A"                                                                            , "\n")
cat ("delta2", "Gamma", "rho1", "rho2", " |", "R1t", "  R2t", "  LNV"                     , "\n")
cat ("-------------------------------------------"                                        , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[1], "-0.1 ", "|", CP[1,1], CP[1,4], CPL[1,1]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[2], "-0.3 ", "|", CP[2,1], CP[2,4], CPL[2,1]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[3], "-0.9 ", "|", CP[3,1], CP[3,4], CPL[3,1]            , "\n")
cat ("\n")
cat ("Model B"                                                                            , "\n")
cat ("delta2", "Gamma", "rho1", "rho2", " |", "R1t", "  R2t", "  LNV"                     , "\n")
cat ("-------------------------------------------"                                        , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[1], "-0.1 ", "|", CP[1,2], CP[1,5], CPL[1,2]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[2], "-0.3 ", "|", CP[2,2], CP[2,5], CPL[2,2]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[3], "-0.9 ", "|", CP[3,2], CP[3,5], CPL[3,2]            , "\n")
cat ("\n")
cat ("Model C"                                                                            , "\n")
cat ("delta2", "Gamma", "rho1", "rho2", " |", "R1t", "  R2t", "  LNV"                     , "\n")
cat ("-------------------------------------------"                                        , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[1], "-0.1 ", "|", CP[1,3], CP[1,6], CPL[1,3]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[2], "-0.3 ", "|", CP[2,3], CP[2,6], CPL[2,3]            , "\n")
cat (dg[1], "   ",dg[2], "   ",p1[3], "-0.9 ", "|", CP[3,3], CP[3,6], CPL[3,3]            , "\n")
}
printres(CP, CPL)

#END


#
#mydeo (c) University of Manchester 2015
#
#mydeo is licensed under the MIT License.
#
#To view a copy of this license, visit <http://opensource.org/licenses/MIT/>.
#
#@author: Pablo Carbonell, SYNBIOCHEM
#@description: Design of experiments routines for combinatorial assembly using R libraries
#
                                        # Use always multiples of 2

repo <- "https://cloud.r-project.org"
if (!require('DoE.base')) {
    if (!require('gmp',quietly=TRUE)) {install.packages('gmp', repos=repo, verbose=FALSE)}
    if (!require('gmp', quietly=TRUE)) {install.packages('numbers', repos=repo, verbose=FALSE)}
    if (!require('crossdes', quietly=TRUE)) {install.packages('crossdes', repos=repo, verbose=FALSE)}
    if (!require('combinat', quietly=TRUE, warn.conflicts = FALSE)) {install.packages('combinat', repos=repo, verbose=FALSE)}
    if (!require('planor', quietly=TRUE)) {install.packages('planor', repos=repo, verbose=FALSE)}
    if (!require('R.utils', quietly=TRUE)) {install.packages('R.utils', repos=repo, verbose=FALSE)}
    if (!require('DoE.base', quietly=TRUE)) {install.packages('DoE.base', repos=repo, verbose=FALSE)}
}

latin.augment <- function(m1, m2) {
    ms <- list()
    for (x in seq(1, max(m1))) {
        ms[[x]] <- m2 + (x-1)*max(m2)
    }
    m4 <- NULL
    for (i in seq(1, ncol(m1))) {
        m3 <- NULL
        for (j in seq(1, ncol(m1))) {
            if (is.null(m3)) {
                m3 <- ms[[ m1[i,j] ]]
            } else {
                m3 <- cbind( m3, ms[[ m1[i,j] ]] )
            }
        }
        if (is.null(m4)) {
            m4 <- m3
        } else {
            m4 <- rbind(m4, m3)
        }

    }
    return(m4)
}

latin <- function(ntotal) {
    if (!require('gmp', quietly=TRUE)) {
        require('numbers', quietly=TRUE)
        useGMP <- FALSE
    } else {
        useGMP <- TRUE
    }
    require('crossdes', quietly=TRUE)
    # Find all prime factors
    if (useGMP) {
	if (ntotal > 1) {
        	m <- factorize(ntotal)
        	m <-  as.integer(m)
	} else {
		m <- c(1)
	}
    } else {
        m <- primeFactors(ntotal)
    }
    sq <- list()
    # Join any 2 * 2 as 4 (orthogonal latin squares only for n >= 3)
    fours <- c()
    while ( (length(m) >=2) && (m[2] == 2) ) {
        if (length(m) > 2) {
            m <- m[3:length(m) ]
            fours <- c(fours, 4)
        } else {
            m <- c(4)
        }
    }
    m <- c(fours, m)
    # Compute orthogonal squares of each factor
    for (n in m) {
        if (n > 2) {
            x <- des.MOLS(n,n)
        } else {
            if (n ==2 ) {
                x <- matrix(c(1,2,2,1), nrow=2)
            } else {
                x <- matrix(c(1))
            }
        }
        sq[[n]] <- x

    }
    # Augment the matrix with all prime factors
    m1 <- sq[[ m[1] ]]
    if (length(m) == 1) {
        return( m1 )
    } else {
        m2 <- sq[[ m[2] ]]
        mx <- latin.augment(m1, m2)
        if (length(m) > 2) {
            for (i in seq(3, length(m))) {
                m3 <- sq[[ m[i] ]]
                mx <- latin.augment(mx, m3)
            }
        }
    }

    return(mx)
}

latin.old <- function(n, nrand = 20) {
    library('crossdes')
    if (n > 2) {
        x <- des.MOLS(n,n)[1:n, 1:n]
    } else {
        if (n ==2 ) {
            x <- matrix(c(1,2,2,1), nrow=2)
        } else {
            x <- matrix(c(1))
        }
    }

#    x <- matrix(1:n, n, n)
#    x <- t(x)
#    for (i in 2:n) {
#        x[i, ] <- x[i, c(i:n, 1:(i-1))]
#    }
    if (n > 2) {
        if (nrand > 0) {
            for (i in 1:nrand) {
                x <- x[sample(n), ]
                x <- x[,sample(n)]
            }
        }
        x <- x[, order(x[1,])]
    }
    return(x)
}

# Generate full permutation or latin square
permut <- function(n, ptype='latin', randomize=TRUE) {
    require('combinat', quietly=TRUE, warn.conflicts = FALSE)
    if (ptype == 'latin') {
        if (randomize) {
            return(latin(n))
        } else {
            return(latin(n))
        }
    } else {
        return(permn(n))
    }
}

# Regular factorial design with implicit S model
doe1 <- function(factors, nlevels, timeout=5) {
    print(factors)
    require('planor', quietly=TRUE)
    require('R.utils', quietly=TRUE)
    require('combinat', quietly=TRUE)
    construct <- planor.factors(
        factors=factors,
        nlevels=nlevels
        )
    const.ffd <- list()
    # We check if we have enough resolution for the model
    HAVERESOLUTION <- TRUE
    # Start with the simplest model: ~S
    res <- 3
    const.total <- prod(construct@fact.info$nlev)
    n <- 1
    const.ffd[[n]] <- NULL
    # Change to verify if we have enough resolution
    units <- 0
    while (units < const.total) {
        # Start with full combinations
        k <- 1
        des <- 0
        units <- const.total
        while (!is.null(des)) {
            des <- NULL
            try(
                evalWithTimeout(
                    des <- regular.design(factors=construct, resolution=res, nunits=const.total/k),
                    timeout=timeout, onTimeout='silent'
                    )
                )
                                        # Simplify S4 structure
            if (!is.null(des)) {
                const.ffd[[n]] <- list(design=slot(des, 'design'), resolution=res)
                units <- dim(const.ffd[[n]]$design)[1]
            }
            k <- k*2
        }
        # Increase to the next model
        n <- n+1
        res <- res+2
    }
    return(const.ffd)
}

# Orthogonal arrays
doe2 <- function(factors, nlevels, timeout=5, seed=888) {
    require('DoE.base', quietly=TRUE)
    const.oa <- list()
    des <- oa.design(factor.names=factors, nlevels=nlevels, seed=seed)
    const.oa[[1]] <- list(design=des, resolution=NULL)
    return(const.oa)
}


##https://github.com/jrfaulkner/spmrf

#' Extract latent process parameters and associated Bayesian credible intervals
#'
#' Extract theta (latent process) parameters from an object with posterior draws and associated Bayesian credible intervals.
#' @param mfit An object containing posterior draws from a \code{spmrf} model fit or \code{stan} model fit.  The object can be of class \code{stanfit}, \code{array}, \code{matrix}, or \code{data.frame}.
#' @param obstype Character string with the name of the probability distribution of the observations.  This controls the back-transformation of the process parameters.  Possible values for \code{obstype} are 'normal', 'poisson', or 'binomial'.
#' @param alpha Controls level for 100*(1-\code{alpha})\% Bayesian credible intervals. Values must be 0 < \code{alpha} < 1.
#' @return Returns a list with the posterior median and posterior (1-\code{alpha}) quantiles of the theta parameter vector.
#' @seealso \code{\link[rstan]{stan}}, \code{\link[rstan]{as.array.stanfit}}, \code{\link[rstan]{as.matrix.stanfit}}, \code{\link[rstan]{as.data.frame.stanfit}}, \code{\link{spmrf}}
#' @export

extract_theta <- function(mfit, obstype="normal",  alpha=0.05){

  if (missing(mfit)) stop("Must specify object with posterior draws from a spmrf or stan model fit.")
  if ( !(class(mfit)[1] %in% c("array", "matrix", "data.frame", "stanfit") ) ) stop("Object must be of class 'stanfit', 'array', 'matrix', or 'data.frame'.  Object must be or be generated from a stan model fit object.")
  if ( !(obstype %in% c("normal", "poisson", "binomial") ) ) stop("Argument 'obstype' must be 'normal', 'poisson', or 'binomial'.")
  if (!(0 < alpha & alpha < 1)) stop("Must specify 'alpha' between 0 and 1.")

  if (class(mfit)[1]=="stanfit") {
  	 if (!requireNamespace("rstan", quietly = TRUE)) {
    			stop("Package 'rstan' needed for this function to work. Please install it.", call. = FALSE)
  	 }
  	tmp.th <- rstan::extract(mfit, "theta")[[1]]
  }
  if (class(mfit)[1]=="array")  {
    nca <- dim(mfit)[2]
	  tmp.th1 <- mfit[ , 1, ]
	  if (nca > 1){
	    for (jj in 2:nca){
	      tmp.th1 <- rbind(tmp.th1, mfit[ ,jj,])
	    }
	  }
	  ath <-  grep(x=dimnames(tmp.th1)[[2]], pattern="theta")
	  zth <-  grep(x=dimnames(tmp.th1)[[2]], pattern="ztheta")
	  thind <- setdiff(ath, zth)
	  tmp.th <- tmp.th1[ , thind]
  }
  if (class(mfit)[1]=="matrix"){
  	ath <-  grep(x=colnames(mfit), pattern="theta")
  	zth <-  grep(x=colnames(mfit), pattern="ztheta")
  	thind <- setdiff(ath, zth)
  	tmp.th <- mfit[ , thind]
  }
  if (class(mfit)[1]=="data.frame") {
  	ath <-  grep(x=names(mfit), pattern="theta")
  	zth <-  grep(x=names(mfit), pattern="ztheta")
  	thind <- setdiff(ath, zth)
  	tmp.th <- as.matrix(mfit[ , thind])
  }
  plow <- alpha/2
  phigh <- 1 - alpha/2

  if (obstype=="normal"){
   tmp.md <- apply(tmp.th, 2, median)
   tmp.l <- apply(tmp.th, 2, quantile, probs=plow)
   tmp.u <- apply(tmp.th, 2, quantile, probs=phigh)
  }
  if (obstype=="poisson"){
   tmp.md <- exp(apply(tmp.th, 2, median))
   tmp.l <- exp(apply(tmp.th, 2, quantile, probs=plow))
   tmp.u <- exp(apply(tmp.th, 2, quantile, probs=phigh))
  }
  if (obstype=="binomial"){
   tmp.md <- plogis(apply(tmp.th, 2, median))
   tmp.l <- plogis(apply(tmp.th, 2, quantile, probs=plow))
   tmp.u <- plogis(apply(tmp.th, 2, quantile, probs=phigh))
  }
   out <- list(postmed=tmp.md, bci.lower=tmp.l, bci.upper=tmp.u)
   out

}


#!/usr/bin/Rscript

# Bhishan Poudel
# Jan 16, 2016

# set up a device driver to plot
#postscript(file='~/Copy/Programming/R/rprograms/plotting/legends/legend3.eps')

par(mar = c(4, 4, 2, 0.1))
plot(rnorm(100), rnorm(100),
     xlab = expression(hat(mu)[0]), ylab = expression(alpha^beta),
     main = expression(paste("Plot of ", alpha^beta, " versus ", hat(mu)[0])))

# turn off device driver
#dev.off()


rawData <- read.csv("data/train.csv")
train <- rawData[1:(nrow(rawData) * 0.7), ]
crossValid <- rawData[(nrow(train) + 1):(nrow(rawData)), ]
test <- read.csv("data/test.csv")

cleaningData <- function(original) {
    if ("Survived" %in% colnames(original)) {
        #usefulCol <- c("Survived", "Pclass", "Sex", "Age", "SibSp","Parch","Fare","Embarked")
        usefulCol <- c("Survived", "Pclass", "Sex", "Age")
    } else {
        #usefulCol <- c("Pclass", "Sex", "Age", "SibSp","Parch","Fare","Embarked")
        usefulCol <- c("Pclass", "Sex", "Age")
    }

    data <- data.matrix(fixNa(original)[, usefulCol])
    cbind(matrix(1, nrow(data), 1), data)
    #fixNa(original)[, usefulCol]
}

fixNa <- function(data) {
    temp <- data
    temp$Age[is.na(temp$Age)] <- mean(temp$Age, na.rm=T)
    temp$Fare[is.na(temp$Fare)] <- mean(temp$Fare, na.rm=T)
    temp$Pclass[is.na(temp$Pclass)] <- mean(temp$Pclass, na.rm=T)
    temp$SibSp[is.na(temp$SibSp)] <- mean(temp$SibSp, na.rm=T)
    temp$SibSp[is.na(temp$Parch)] <- mean(temp$Parch, na.rm=T)
    temp
}

mySigmoid <- function(z) {
    1.0 / (1.0 + exp(-z));
}

costFunc <- function(theta, X, y) {
    sum(cbind(y, 1 - y) * cbind(log(sigmoid(X %*% theta)), log(1 - sigmoid(X %*% theta)))) / -nrow(X)
}

gradient <- function(theta, X, y) {
    (t(X) %*% (sigmoid(X %*% theta) - y)) / nrow(X);
}

learning <- function(train, alpha, iterNum) {
    cleanTrain <- cleaningData(train)
    X <- cleanTrain[, -2]
    y <- cleanTrain[, 2]
    theta <- matrix(0, ncol(X), 1)
    for (i in 1:iterNum) {
        theta <- theta - alpha * gradient(theta, X, y)
    }
    theta
}

builtInLearning <- function(train) {
    glm(Survived~., family = binomial, data=train)
}

crossValidate <- function(validateSet, theta) {
    cleanedData <- cleaningData(validateSet)
    X <- cleanedData[, -2]
    y <- cleanedData[, 2]
    m <- nrow(X)
    p <- rep(c(0), m)
    correct <- 0
    t_neg <- 0
    t_pos <- 0
    f_neg <- 0
    f_pos <- 0
    for (i in 1:m) {
        rate <- sigmoid(X[i,] %*% theta)

        if (rate >= 0.5 && y[i] == 1) {
            t_pos <- t_pos + 1
        } else if (rate < 0.5 && y[i] == 1) {
            t_neg <- t_neg + 1
        } else if (rate >= 0.5 && y[i] == 0) {
            f_neg <- f_neg + 1
        } else if (rate < 0.5 && y[i] == 0) {
            f_pos <- f_pos + 1
        }

        if ((rate >= 0.5 && y[i] == 1) || (rate < 0.5 && y[i] == 0)) {
            correct <- correct + 1
        }

    }

    precision <- (t_pos / (t_pos + f_pos))
    recall <- (t_pos / (t_pos + f_neg))
    f1 <- (precision * recall) / (precision + recall)
    #acc <- (t_pos + t_neg) / (t_pos + t_neg + f_pos + f_neg)
    acc <- correct / m

    list(precision = precision, recall = recall, f1 = f1, acc = acc)
}

myPredict <- function(test, theta) {
    X <- cleaningData(test)
    m <- nrow(X)
    p <- rep(c(0), m)

    for (i in 1:m) {
        rate <- sigmoid(X[i,] %*% theta)

        if (rate >= 0.5) {
            p[i] <- 1
        } else {
            p[i] <- 0
        }

    }

    data.frame(PassengerId=test[,"PassengerId"], Survived=p)
}


# 4. faza: Napredna analiza podatkov

# CLUSTERING ###################################################################

#podatki za zdravstvo po letu 2011 vedno slabši zato je najbolj optimalno leto za analizo 2011

# tabela:

X <- zivljenje %>% filter(leto == "2011") %>% filter(!drzava %in% c("Bulgaria","Luxembourg"))
X$drzava[X$drzava == "Czech Republic"] <- "Czech Rep."
X.norm <- X %>% dplyr::select(pricakovana.starost, kg.na.osebo, odstotek.BDP.ki.gre.v.zdravstvo, tveganje.revscine)%>%
  scale()
rownames(X.norm) <- X$drzava
X.norm <- X.norm[1:29, -1]

## HIERARHIČNO

#funkcije s predavanj:

hc.kolena = function(dendrogram, od = 1, do = NULL, eps = 0.5) {
  # število primerov in nastavitev parametra do
  n = length(dendrogram$height) + 1
  if (is.null(do)) {
    do = n - 1
  }
  # k.visina je tabela s štirimi stolpci
  # (1) k, število skupin
  # (2) višina združevanja
  # (3) sprememba višine pri združevanju
  # (4) koleno: ali je točka koleno?
  k.visina = tibble(
    k = as.ordered(od:do),
    visina = dendrogram$height[do:od]
  ) %>%
    # sprememba višine
    mutate(
      dvisina = visina - lag(visina)
    ) %>%
    # ali se je intenziteta spremembe dovolj spremenila?
    mutate(
      koleno = lead(dvisina) - dvisina > eps
    )
  k.visina
}

# iz tabele k.visina vrne seznam vrednosti k,
# pri katerih opazujemo koleno
hc.kolena.k = function(k.visina) {
  k.visina %>%
    filter(koleno) %>%
    dplyr::select(k) %>%
    unlist() %>%
    as.character() %>%
    as.integer()
}

# narišemo diagram višin združevanja
diagram.kolena = function(k.visina) {
  k.visina %>% ggplot() +
    geom_point(
      mapping = aes(x = k, y = visina),
      color = "red"
    )+
    geom_line(
      mapping = aes(x = as.integer(k), y = visina),
      color = "red"
    )+
    geom_point(
      data = k.visina %>% filter(koleno),
      mapping = aes(x = k, y = visina),
      color = "blue", size = 2
    )+
    ggtitle(paste("Kolena:", paste(hc.kolena.k(k.visina), collapse = ", "))) +
    xlab("število skupin (k)") +
    ylab("razdalja pri združevanju skupin") +
    theme_classic()
}

diagram.skupine = function(podatki, oznake, skupine, k) {
  podatki = podatki %>%
    bind_cols(skupine) %>%
    rename(skupina = ...2)

  d = podatki %>%
    ggplot(
      mapping = aes(
        x = x, y = y, color = skupina
      )
    ) +
    geom_point() +
    geom_label(label = oznake, size = 2) +
    scale_color_hue() +
    theme_classic()

  for (i in 1:k) {
    d = d + geom_encircle(
      data = podatki %>%
        filter(skupina == i)
    )
  }
  d
}

library(rgeos)
library(ggalt)

dendrogram <- dist(X.norm) %>% hclust(method = "ward.D")

r = hc.kolena(dendrogram)
diagram.kolena(r)
# -> 4 skupine

#zakomentirano da ne izpisuje v rmd
#plot(dendrogram, hang=-1, cex=0.4, main = "drzava", labels = X$drzava)
#rect.hclust(dendrogram,k=4,border="red")

skupine = dendrogram %>% cutree(k = 4) %>% as.ordered()
skupine

diagram.skupine(X.norm, colnames(X.norm), skupine, 2 )

#drzave <- attributes(X.norm)$dimnames[[1]]  # dobimo imena, ki jih spremenimo potem v stolpce (to ni df)
#drzave.x.y = as_tibble(X.norm %>% cmdscale(k = 2)) #%>% bind_cols(drzave) %>%
#  rename(drzava = ...3, x = V1, y = V2)

# Narišemo države tako, da jih pobarvamo glede na pripadnost skupini
#  diagram.skupine(drzave.x.y, drzave.x.y$drzava, skupine, 4)

data("World")
evropa <- World %>% filter (continent == 'Europe')
skupina <- data.frame(name = X$drzava, skupine=factor(skupine))
zem <- merge(x = evropa, y =  skupina)
grupiranje.map <- tm_shape(zem) + tm_polygons("skupine", palette = "Pastel1", popup.vars = c("Skupina: " = "skupine"))+tmap_mode("view")

grupiranje.map

# NAPOVED ######################################################################

# za napoved pricakovane zivljenjske dobe v Sloveniji za leto 2020
# uvozila nove podatke, z daljšim časovnim obdobjem

pricakovana.slo <- read_csv("podatki/HFA_43_EN.csv",
                        skip = 25,
                        na = "-",
                        locale = locale(encoding = "Windows-1250"))%>%
  filter(COUNTRY == "SVN")%>%
  dplyr::select(YEAR, VALUE )

library(ranger)

Lag <- function(x, n){c(rep(NA, n), x)[1:length(x)]}

naredi.df <- function(x){
  data.frame(pricakovana = x,
             pricakovana1 = Lag(x, 1),
             pricakovana2 = Lag(x, 2),
             pricakovana3 = Lag(x, 3),
             pricakovana4 = Lag(x, 4))

}

df <- naredi.df(pricakovana.slo$VALUE)
model = ranger(formula = pricakovana ~ ., data = df %>% drop_na())

n = nrow(df)

df2 <- naredi.df(c(pricakovana.slo$VALUE, NA))
napoved <- predict(model, data = df2[n+1,])$predictions
df2[n+1,1] = napoved

pricakovanje <- as_tibble(data.frame(
  c(1985:2020),
  df2$pricakovana))

napoved.graf <- ggplot(pricakovanje) + geom_line(mapping = aes(x = c.1985.2020., y = df2.pricakovana), color = "red")+
  geom_line(mapping = aes(x = c.1985.2020., y = df2.pricakovana, color = c.1985.2020. <= 2019), show.legend = FALSE)+
  labs(
    x = "Leto",
    y = "Pričakovana življenjska doba",
    title = "Gibanje pričakovane življenjske dobe v Sloveniji in napoved za leto 2020"
  )

####
#samo da ugotovim korelacijo:
ggpairs(data.frame(X.norm))


#
# R-Code zu NOT-Statistik 2. Auflage
#

# Stand 30.01.2021

## Kapitel 3 ##
#

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 51: Daten in R einlesen
# Vorbereitung: Daten-Datei "PLZ_0.CSV" lokal speichern
PLZ.0 = read.csv2(file.choose(), stringsAsFactors = TRUE)
# erstellt Daten-Container "PLZ.0"
# read.csv2() liest eine csv-Datei mit Komma als Dezimaltrenner in "PLZ.0" ein
# file.choose() öffnet den Explorer zur Dateiauswahl, ausgewählt wird "PLZ_0.CSV"
# stringsAsFactors = TRUE importiert Buchstaben/Zeichenketten als Faktoren

PLZ.0$Beginn=as.Date(PLZ.0$Beginn, "%d.%m.%Y")
PLZ.0$Ende=as.Date(PLZ.0$Ende, "%d.%m.%Y")
# PLZ.0$[Spaltenname] wählt Spalte aus
# Datumsformatierung für Spalten "Beginn" und "Ende"

str(PLZ.0) # zeigt eine Übersicht der PLZ.0-Daten und Formate an

attach(PLZ.0) # PLZ.0-Merkmale so direkt über Spaltennamen auswählbar

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 51: Balkendiagramm
# plot() zeichnet Balkendiagramm für attributive Merkmale
plot(Lieferant)
plot(Kunde)
plot(Methode)
plot(Review)
plot(Komplexität)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 51: Einzelwertdiagramme
# stripchart() zeichnet Einzelwertdiagramm
stripchart(PL, vertical=TRUE, method="stack", pch=20, main="PL")
# vertical=TRUE: Punkte werden vertikal eingezeichnet
# "stack": gleiche Werte stapeln
# pch: point character, 20 ist ein ausgefüllter Kreis
# main: setzt Titel über die Grafik
stripchart(PMa, vertical=TRUE, method="stack", pch=20, main="PMa")
stripchart(Abteilungen, vertical=TRUE, method="stack", pch=20, main="Abteilungen")
stripchart(Laufzeit, vertical=TRUE, method="stack", pch=20, main="Laufzeit")

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 52: Zeitreihendiagramme für 1 Merkmal
# plot() zeichnet Zeitreihendiagramm für variable Merkmale
plot(PL, type="b")	# type="b": both, d. h. Linien und Punkte zeichnen
plot(PMa, type="b")
plot(Abteilungen, type="b")
plot(Laufzeit, type="b")

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 52: Zeitreihendiagramm gemeinsam für Beginn und Ende
plot(Beginn, type="b", pch=20, xlab="Index")
lines(Ende, type="b", col="blue", pch=20)
# Hinzufügen der Linien und Punkte für 'Ende'
# col: color, Farbe für Linie und Punkte

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 56: Zeilennummern für Einträge finden
# which() liefert Zeilennummern mit vorgegebenen Kriterien
which(Lieferant == "Ja")
which(Kunde == "nein ")
which(Review == "eventuell" | Review == "vielleicht")
# | ist das Zeichen für ODER
which(PL > 50)
which(Laufzeit < 0)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 57: Einlesen der überarbeiteten Daten
setwd("~/Arbeit/Buch/SPM/R")

detach(PLZ.0)
# Die Merkmalsnamen im R-Speicher müssen eindeutig sein. Da die Spaltennamen in "PLZ_0.CSV" und "PLZ_1.CSV"
# identisch sind, wird zuerst die alte Daten-Datei aus dem direkten R-Speicher entfernt. Sie sind mit der
# Angabe "PLZ.0$[Spaltenname]" weiter verfügbar.

# Vorbereitung: Daten-Datei "PLZ_1.CSV" lokal speichern
PLZ.1 = read.csv2(file.choose(), stringsAsFactors = TRUE)
# erstellt Daten-Container "PLZ.1"
# eingelesen in "PLZ.1" wird jetzt die Datei "PLZ_1.CSV"

# Formatierung des Datums
PLZ.1$Beginn=as.Date(PLZ.1$Beginn, "%d.%m.%Y")
PLZ.1$Ende=as.Date(PLZ.1$Ende, "%d.%m.%Y")

str(PLZ.1) # Übersicht Einträge in "PLZ.1"
attach(PLZ.1) # Daten-Container "PLZ.1" im direkten R-Speicher verfügbar machen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 57: Erstellen der Grafiken mit PLZ.1
# Balkendiagramme
plot(Lieferant)
plot(Kunde)
plot(Review)

# Einzelwertdiagramme
stripchart(PL, vertical=TRUE, method="stack", pch=20, main="PL")
stripchart(Laufzeit, vertical=TRUE, method="stack", pch=20, main="Laufzeit")

# Zeitreihendiagramme
plot(PL, type="b")
plot(Laufzeit, type="b")

## Kapitel 4 ##
#
# Grafiken

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 67: Boxplots
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ.1) verfügbar gemacht

boxplot(Laufzeit ~ Lieferant, pch=8, col="lightgrey", lty=1)
# erstellt Boxplot für Laufzeit nach Lieferant
# pch=8: Extremwerte werden als Stern angezeigt
# col="lightgrey": Kästen werden hellgrau ausgefüllt
# lty=1: Linien werden durchgezogen gezeichnet
boxplot(Laufzeit ~ Kunde, pch=8, col="lightgrey", lty=1)
boxplot(Laufzeit ~ Methode, pch=8, col="lightgrey", lty=1)
boxplot(Laufzeit ~ Review, pch=8, col="lightgrey", lty=1)
boxplot(Laufzeit ~ Komplexität, pch=8, col="lightgrey", lty=1)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 69: Haupteffekte-Diagramm
# Definieren einer Haupteffekte-Diagramm-Funktion: HEdiagramm
HEdiagramm = function(x,y){
  mw = aggregate(y ~ x, data=PLZ.1, FUN=mean)
  # erstellt Variable mw
  # speichert die Mittelwerte (mw) von y je Stufe von x aus den Daten PLZ.1 über die Funktion (FUN) mean darin
  plot(mw, lty="blank", xlab=deparse(substitute(x)), ylab=deparse(substitute(y)))
  # zeichnet ein leeres Diagramm mit Achsen und Achsen-Beschriftung
  lines(mw) # fügt Verbindungslinie der Mittelwerte hinzu
  points(mw, pch=19) # zeichnet Punkte für die Mittelwerte ein
}
HEdiagramm(Lieferant,Laufzeit)
HEdiagramm(Kunde,Laufzeit)
HEdiagramm(Methode,Laufzeit)
HEdiagramm(Review,Laufzeit)
HEdiagramm(Komplexität,Laufzeit)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 72: Streudiagramm-Matrix (im Buch: Wechselwirkungs-Diagramm)
require(lattice)
# für die Streudiagramm-Matrix muss das Package "lattice" installiert sein
# Pakete in R installieren (Internetverbindung notwendig!):
# Pakete > Installiere Pakete > OK > Paketnamen in der Liste finden > OK

PLZ.1.variabel = subset(PLZ.1, select=c(PL,PMa,Abteilungen,Laufzeit))
# subset() erstellt Teilmenge aus PLZ.1, die alle vier variablen Merkmale PL, PMa, Abteilungen und Laufzeit enthält
splom(~PLZ.1.variabel)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 76: Wechselwirkungs-Diagramm
interaction.plot(Lieferant,Kunde,Laufzeit, type="b", col=1:nlevels(Kunde))
# interaction.plot ist Funktion für Wechselwirkungs-Diagramme
# hier: Lieferant auf x-Achse, Kunde für unterschiedliche Linien
# type="b": Linien und Punkte ("both") zeichnen
# col=1:nlevels(Kunde): Farben ("colors") der Linien und Punkte
interaction.plot(Lieferant,Methode,Laufzeit, type="b", col=1:nlevels(Methode))
interaction.plot(Lieferant,Review,Laufzeit, type="b", col=1:nlevels(Review))
interaction.plot(Lieferant,Komplexität,Laufzeit, type="b", col=1:nlevels(Komplexität))
interaction.plot(Kunde,Methode,Laufzeit, type="b", col=1:nlevels(Methode))
interaction.plot(Kunde,Review,Laufzeit, type="b", col=1:nlevels(Review))
interaction.plot(Kunde,Komplexität,Laufzeit, type="b", col=1:nlevels(Komplexität))
interaction.plot(Methode,Review,Laufzeit, type="b", col=1:nlevels(Review))
interaction.plot(Methode,Komplexität,Laufzeit, type="b", col=1:nlevels(Komplexität))
interaction.plot(Review,Komplexität,Laufzeit, type="b", col=1:nlevels(Komplexität))

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 81: 3D-Streudiagramme
cloud(Laufzeit ~ PL + PMa, scales = list(arrows=FALSE))
# erstellt ein 3D-Streudiagramm (Punktewolke / cloud)
# für Laufzeit (Z-Achse) mit PL (Y-Achse)  und PMa (X-Achse)
# scales = list(arrows=FALSE): Achsenbeschriftung (Skala) mit Zahlen statt Pfeilen
cloud(Laufzeit ~ PL + Abteilungen, scales = list(arrows=FALSE))
cloud(Laufzeit ~ PL + PMa, scales = list(arrows=FALSE))

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 84: Matrixplot mit attributiven Merkmalen
PLZ.1.variabel = subset(PLZ.1, select=c(PL,PMa,Abteilungen,Laufzeit))
#  subset() erstellt Teilmenge aus PLZ.1, die alle variablen Merkmale enthält

symbole = trellis.par.get("superpose.symbol")
# Eigenschaften von Gruppierungs-Symbolen in "symbole" gespeichert

splom(~PLZ.1.variabel, # Streudiagramm-Matrix für alle variablen Merkmale
	groups=Komplexität, # unterschieden nach Komplexitäts-Stufen
	key=list(columns=3,
		points=list(pch=symbole$pch[1:3], col=symbole$col[1:3]),
		text=list(levels(Komplexität)))
	# key definiert die Legende (Liste mit Vorgaben):
	# columns=3: Anzahl Legenden-Spalten über der Grafik 3
	# points=... : Vorgabe der Symbole und Farben
	# text=... : Für jedes Legenden-Symbol wird die Bezeichnung/Level von Komplexität eingefügt
	)

## Kapitel 5 ##
#
# Erstes statistisches Prozess-Modell

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 98: Erstes SPM
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ.1) verfügbar gemacht

require(car)
# für die hier verwendeten Kontraste und Varianzanalyse (ANOVA) wird das Paket car benötigt

lm.1 = lm(Laufzeit ~ PL + PMa + Abteilungen + Lieferant + Kunde + Methode + Review + Komplexität
          + PL:PMa + PL:Abteilungen + PL:Lieferant + PL:Kunde + PL:Methode + PL:Review + PL:Komplexität
          + PMa:Abteilungen + PMa:Lieferant + PMa:Kunde + PMa:Methode + PMa:Review + PMa:Komplexität
          + Abteilungen:Lieferant + Abteilungen:Kunde + Abteilungen:Methode + Abteilungen:Review + Abteilungen:Komplexität
          + Lieferant:Kunde + Lieferant:Methode + Lieferant:Review + Lieferant:Komplexität
          + Kunde:Methode + Kunde:Review + Kunde:Komplexität
          + Methode:Review + Methode:Komplexität
          + Review:Komplexität
          + I(PL^2) + I(PMa^2),
          contrasts=list(Lieferant=contr.Sum,Kunde=contr.Sum,Methode=contr.Sum,Review=contr.Sum,Komplexität=contr.Sum),
          data=PLZ.1)
# in Container lm.1 sind die Ergebnisse des ersten SPMs gespeichert
# lm: linear model für Zielgröße Laufzeit (vor der Tilde ~)
# PL:PMa (z. B.) Wechselwirkung, durch ":" angegeben
# I(PL^2) quadratischer Effekt von PL
# contrasts: Art der Effekt-Berechnung von attributiven Merkmalen

Anova(lm.1, type=3)
# gibt eine Varianzanalyse-Tabelle mit dem Berechnungstyp 3 aus

## Kapitel 6 ##
#
# SPM vereinfachen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 103: Auswahl Effekt-Kodierung
getOption("contrasts")
# zeigt die Einstellungen für die Kontraste an:
# erster Eintrag für Faktoren ohne Rangfolge (Voreinstellung: contr.treatment)
# zweiter Eintrag für Faktoren mit Rangfolge (Voreinstellung: contr.poly)

options(contrasts=c("contr.Sum","contr.poly"))
# setzt die Kontraste global für alle Modelle
# contr.Sum: Effekt-Kodierung für attributive Merkmale ohne Rangfolge der Stufen
# contr.poly: polynomiale Kodierung für attributive Merkmale mit Rangfolge der Stufen
getOption("contrasts")
# geänderte Kontrast-Einstellung: "contr.Sum" und "contr.poly"

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 120: Unwichtige Einflüsse ausschließen (1/2)
# Daten PLZ_1.CSV sind eingelesen
# Das SPM lm.1 ist berechnet

lm.1.step = step(lm.1, direction="both")
# step: schrittweise Auswahl wichtiger Einflüsse über AIC
# direction="both": Ausschluss und Hinzunahme in der Auswahl-Strategie

require(car) # Paket car laden

Anova(lm.1.step, type=3)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 121: Unwichtige Einflüsse ausschließen (2/2)
# Daten PLZ_1.CSV sind eingelesen

lm.2 = lm(Laufzeit ~ PL + PMa + Abteilungen + Lieferant + Kunde + Methode + Review + Komplexität
          + I(PMa^2)
          + PL:PMa
          + Abteilungen:Methode
          + Lieferant:Kunde
          + Kunde:Komplexität
          + Methode:Review,
          data = PLZ.1)

Anova(lm.2, type=3)

## Kapitel 7 ##
#
# Modell-Qualität prüfen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 133: Modell-Qualitäts-Kennzahlen R², R²(prog) und S
# lm.2 wurde berechnet

SST = sum((Laufzeit-mean(Laufzeit, na.rm=TRUE))^2)
# berechnet SST und speichert Wert in "SST"
SSE = sum(resid(lm.2)^2)
# berechnet SSE und speichert Wert in "SSE"
R2 = 1-SSE/SST # berechnet R² und speichert Wert in "R2"
R2 # zeigt Wert von "R2" an, hier: 0.8744451 = 87,44%

PRESS = sum((resid(lm.2)/(1-hatvalues(lm.2)))^2)
# berechnet PRESS und speichert Wert in "PRESS"
PRESS # zeigt Wert von "PRESS" an
R2.prog = 1-PRESS/SST # berechnet R²_prog und speichert Wert in "R2.prog"
R2.prog # zeigt Wert von "R2.prog" an, hier: 0.8366248 = 83,66%

S.spm = sqrt(SSE/df.residual(lm.2))
# berechnet Modell-Standardabweichung S und speichert Wert in "S.spm"
# df.residual ermittelt die Freiheitsgrade der Residuen, hier: n-k=115
S.spm # zeigt Wert von "S.spm" an, hier: 8.533396 = 8,53 Tage

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 141: Residuendiagramme: Wahrscheinlichkeitsnetze
# lm.2 wurde berechnet

qqnorm(residuals(lm.2), xlab="Normalverteilungs-Quantile", ylab="Residuen",
	main="Wahrscheinlichkeitsnetz", pch=20)
qqline(residuals(lm.2), col="blue")
# qqnorm zeichnet Wahrscheinlichkeitsnetz für Normalverteilung
# residuals liefert Residuen
# xlab, ylab, main: Beschriftung x-Achse, y-Achse und Titel
# qqline zeichnet Ideallinie (hier: blau)

qqnorm(rstandard(lm.2), xlab="Normalverteilungs-Quantile", ylab="standardisierte Residuen",
	main="W.-Netz", pch=20)
qqline(rstandard(lm.2), col="blue")
# rstandard liefert standardisierte Residuen

qqnorm(rstudent(lm.2), xlab="Normalverteilungs-Quantile", ylab="studentisierte Residuen",
	main="W.-Netz", pch=20)
qqline(rstudent(lm.2), col="blue")
# rstudent liefert studentisierte Residuen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 142: Residuendiagramme: Anpassungen vs. Residuen und Beobachtungsnr. vs. Residuen
# lm.2 wurde berechnet

plot(fitted(lm.2), residuals(lm.2), xlab="Angepasste Werte für Laufzeit", ylab="Residuen", main="Angepasste Werte vs. Residuen", pch=20)
abline(h=0, col="blue")
# fitted liefert die angepassten Werte für die Laufzeit
# abline zeichnet eine Referenzlinie ein, h: horizontal

plot(residuals(lm.2), type="b", xlab="Beobachtungsnummer", ylab="Residuen", main="Beobachtungsnummer vs. Residuen", pch=20)
abline(h=0, col="blue")
# type="b" zeichnet Punkte und Linien ("both")

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 143: Residuendiagramme: Auffällige Residuen finden
# lm.2 wurde berechnet

PLZ.1.SPM = cbind(PLZ.1,Fit=fitted(lm.2),Resi=residuals(lm.2))
# cbind: column-bind, hängt Spalten aneinander
# erzeugt Container PLZ.1.SPM mit den Daten PLZ.1 sowie den
# Anpassungen (Fit) und Residuen (Resi)

PLZ.1.SPM[which(residuals(lm.2) < -20),]
# zeigt die Zeile(n) aus PLZ.1.SPM an, für die die Residuen kleiner -20 sind

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 158: Modell-Qualitäts-Kennzahlen: Test auf Normalverteilung für Residuen
# lm.2 wurde berechnet

require(nortest)
# für den Anderson-Darling-Test wird das Paket "nortest" benötigt
ad.test(residuals(lm.2))
# berechnet den Anderson-Darling-Test auf Normalverteilung (ad.test) und gibt die Werte aus

## Kapitel 8 ##
#
# Modell-Interpretation und Prognose

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 166: Effektediagramme
# lm.2 wurde berechnet

require(effects) # für die Effektdiagramme muss das Paket "effects" installiert sein

# Haupteffekte-Diagramme mit großem E bei Effect
plot(Effect("PL", lm.2, ylim=c(91,156)))
	# ylim gibt Wertebereich der y-Achse an
plot(Effect("PMa", lm.2, ylim=c(91,156)))
plot(Effect("Abteilungen", lm.2, ylim=c(91,156)))
plot(Effect("Lieferant", lm.2, ylim=c(91,156)))
plot(Effect("Kunde", lm.2, ylim=c(91,156)))
plot(Effect("Methode", lm.2, ylim=c(91,156)))
plot(Effect("Review", lm., ylim=c(91,156),2))
plot(Effect("Komplexität", lm.2, ylim=c(91,156)))

# Wechselwirkungsdiagramme mit kleinem e bei effect
plot(effect("PL:PMa", lm.2, ylim=c(72,168)))
plot(effect("Abteilungen:Methode", lm.2, ylim=c(72,168)))
plot(effect("Lieferant:Kunde", lm.2, ylim=c(72,168)))
plot(effect("Kunde:Komplexität", lm.2, ylim=c(72,168)))
plot(effect("Methode:Review", lm.2, ylim=c(72,168)))

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 168: Quantile und Auswahl von Projekten
PLZ.1[PL >= quantile(PL, .75)
      & PMa >= quantile(PMa, .75)
      & Laufzeit >= quantile(Laufzeit, .75),]
# [... ,] gibt Auswahlkriterium an
# quantile(x, .75) berechnet 75%-Quantil von x
# Auswahl PL >= Q_75(PL)
# und (&) PMa >= Q_75(PMa)
# und (&) Laufzeit >= Q_75(Laufzeit)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 174: Kontur- und Wirkungsflächendiagramme Laufzeit
# lm.2 wurde berechnet

require(lattice) # Pakte lattice laden

# Gitter-Stützpunkte berechnen
PL.p = seq(min(PL), max(PL), length.out=100)
PMa.p = seq(min(PMa), max(PMa), length.out=100)
# seq() erstellt eine Sequenz von Werten
Abteil.p = c(1,3,6)
punkte = list(PL=PL.p, PMa=PMa.p, Abteilungen=Abteil.p)
# list() erstellt eine Liste
gitter = expand.grid(punkte)
# erstellt das Gitter für die Stützpunkte

gitter.niedrig = cbind(gitter,
	data.frame(Lieferant="nein", Kunde="nein",
	Methode="SiSi", Review="nein",
	Komplexität="niedrig"))
# data.frame() erstellt eine Datenstruktur
gitter.niedrig[, "Prognose"] = c(predict(lm.2, gitter.niedrig))
# mit [,...] wird an den vorhandenen data.frame eine Spalte angefügt
# predict(modell,daten) berechnet Prognosen für "daten", hier für gitter.niedrig

gitter.hoch = cbind(gitter,
	data.frame(Lieferant="ja", Kunde="ja",
	Methode="PDCA", Review="ja",
	Komplexität="hoch"))
gitter.hoch[, "Prognose"] = c(predict(lm.2, gitter.hoch))

# Konturdiagramme
contourplot(Prognose ~ PL*PMa | Abteilungen,
	data=gitter.niedrig, main="Kontur niedrig",
	region=TRUE,cuts=10^3, contour=FALSE,
	col.regions=rainbow(2000))
# contourplot() erstellt das Konturdiagramm
# Prognose ~ PL*PMa | Abteilungen: Höhenlinien aus "Prognose",
# x- und y-Achse PMa und PL,
# unterschiedliche Grafiken je Wert in "Abteilungen"

contourplot(Prognose ~ PL*PMa | Abteilungen,
	data=gitter.hoch, main="Kontur hoch",
	region=TRUE,cuts=10^3, contour=FALSE,
	col.regions=rainbow(2000))

# Wirkungsflächendiagramme
wireframe(Prognose ~ PL*PMa | Abteilungen,
	data=gitter.niedrig, main="Wirkungsfläche niedrig",
	zlab="", colorkey=FALSE, shade=TRUE, drape=TRUE,
	scales=list(arrows=FALSE), light.source = c(0,2,2))
# wireframe() erstellt das Wirkungsflächendiagramm
# Achsen und Grafiken wie in countourplot (s. o.)

wireframe(Prognose ~ PL*PMa | Abteilungen,
	data=gitter.hoch, main="Wirkungsfläche hoch",
	zlab="", colorkey=FALSE, shade=TRUE, drape=TRUE,
	scales=list(arrows=FALSE), light.source = c(0,2,2))

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 187: Koeffizienten des vereinfachten SPMs ausgeben
# lm.2 wurde berechnet

round(lm.2$coef,2) # zeigt Koeffizienten von lm.2 an

str(PLZ.1) # zeigt Beschreibung der Daten inkl. Stufen von attributiven Einflussgrößen an

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 195 Prognosen für Laufzeit
# lm.2 wurde berechnet

# Einstellwerte vorgeben
Daten.neu = data.frame(Lieferant="ja", Kunde="nein",
	Methode="PDCA", Review="ja",
	Komplexität=c("hoch","mittel","niedrig"),
	PL=10, PMa=5, Abteilungen=2)
# data.frame() erstellt eine Datenstruktur
# Spalten werden aufgefüllt, so dass alle Spalten dieselbe Länge haben

# Prognose berechnen
Prognose=predict(lm.2, Daten.neu)

cbind(Daten.neu,Prognose)
# cbind() verbindet Spaltenweise (column-bind)
# Ergebnis: Anzeige der Einstellwerte und Prognosen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 198: Vertrauens- und Prognosebereiche für Laufzeit
# lm.2 wurde berechnet

# Einstellwerte vorgeben
Daten.neu = data.frame(Lieferant="ja", Kunde="nein",
	Methode="PDCA", Review="ja",
	Komplexität=c("hoch","mittel","niedrig"),
	PL=10, PMa=5, Abteilungen=2)

# Prognose berechnen
Prognose=round(predict(lm.2, Daten.neu),2)
# round() rundet Werte, hier auf 2 Nachkommastellen

# Obere Grenze 98% Vertrauensbereich berechnen
OGW.KI=round(predict(lm.2, Daten.neu, interval="confidence", level=0.98)[,3],2)
# [,3] wählt dritte Spalte aus, die die OGW angibt

# Obere Grenze 98% Prognosebereiche berechnen
OGW.PI=round(predict(lm.2, Daten.neu, interval="prediction", level=0.98)[,3],2)

cbind(Prognose,OGW.KI,OGW.PI)
# cbind() verbindet Spaltenweise (column-bind)
# Ergebnis: Anzeige der Prognosen und obere Streubereichsgrenzen

## Kapitel 9 ##
#
# Prozess-Simulation

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 206:  Anzahl Werte für Lieferant
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ_1.CSV) verfügbar gemacht
table(Lieferant)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 207: Monte Carlo-Simulation
# lm.2 wurde berechnet

Simu=10^4 # Anzahl Simulationen in "Simu" speichern

simu.attr=function(Merkmal,Simu) {
	sample(rep(levels(Merkmal),rmultinom(1,Simu,prob=table(Merkmal))),Simu)
	}
# Funktion "simu.attr" für die Einstellwerte der attributiven Merkmale:
# 2 Werte: Merkmal und Anzahl (Simu)
# sample() zieht eine Stichprobe aus den Werten
# rep(a,b) wiederholt den Eintrag "a" b Mal
# levels(Merkmals) Stufen des Merkmals
# rmultinom: Zufallszahlen der Multinomialverteilung (2 oder mehr Gruppen im Merkmal)
# rmultinom(a,b,c) erzeugt a Mal Zufallswerte, je Durchlauf b Werte mit den Wahrscheinlichkeiten c je Stufe des Merkmals
# prog=table(Merkmal) gibt die Anzahl Werte je Stufe wieder, die in rmultinom automatisch in Anteile umgewandelt werden

sim.Lief=simu.attr(Lieferant,Simu)
# speichert Zufallswerte für Lieferant in sim.Lief
sim.Kund=simu.attr(Kunde,Simu)
sim.Meth=simu.attr(Methode,Simu)
sim.Rev=simu.attr(Review,Simu)
sim.Kompl=simu.attr(Komplexität,Simu)

sim.PL=abs(rnorm(Simu, mean(PL), sd(PL)))
# speichert Zufallswerte für PL in sim.PL
# abs() berechnet den Absolutwert
sim.PMa=ceiling(abs(rnorm(Simu, mean(PMa), sd(PMa))))
# ceiling berechnet die nächstgrößere ganze Zahl
sim.Abt=ceiling(abs(rnorm(Simu, mean(Abteilungen),sd(Abteilungen))))

# Zusammenstellung der Daten für die Monte Carlo-Simulation
sim.daten = data.frame(Lieferant=sim.Lief,Kunde=sim.Kund,Methode=sim.Meth,Review=sim.Rev,
	Komplexität=sim.Kompl,PL=sim.PL,PMa=sim.PMa,Abteilungen=sim.Abt)

# Berechnung der simulierten Laufzeit
Laufzeit.sim=predict(lm.2,sim.daten)
MC.daten=cbind(sim.daten,Laufzeit.sim)

# Boxplot simulierte Laufzeit nach Review, Methode und Komplexität
boxplot(Laufzeit.sim ~ Review+Methode+Komplexität, pch=8, col="lightgrey", lty=1,
        axes=FALSE, xlab="", ylab="", data=MC.daten)
mtext(side=1, line=3.5, at=c(2.5,6.5,10.5), levels(Komplexität))
mtext(side=1, line=3.5, at=-2.0, adj=c(0), "Komplexität")
mtext(side=1, line=2, at=seq(1.5,11.5,by=2), levels(Methode))
mtext(side=1, line=2, at=-2.0, adj=c(0), "Methode")
mtext(side=1, line=0.5, at=1:12, levels(Review))
mtext(side=1, line=0.5, at=-2.0, adj=c(0), "Review")
axis(1, at=1:12, labels=NA)
axis(2, las=2)
box()

# Boxplot simulierte Laufzeit nach Lieferant, Kunde und Komplexität
boxplot(Laufzeit.sim ~ Lieferant+Kunde+Komplexität, pch=8, col="lightgrey", lty=1,
        axes=FALSE, xlab="", ylab="", data=MC.daten)
mtext(side=1, line=3.5, at=c(2.5,6.5,10.5), levels(Komplexität))
mtext(side=1, line=3.5, at=-2.0, adj=c(0), "Komplexität")
mtext(side=1, line=2, at=seq(1.5,11.5,by=2), levels(Kunde))
mtext(side=1, line=2, at=-2.0, adj=c(0), "Kunde")
mtext(side=1, line=0.5, at=1:12, levels(Lieferant))
mtext(side=1, line=0.5, at=-2.0, adj=c(0), "Lieferant")
axis(1, at=1:12, labels=NA)
axis(2, las=2)
box()

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 208: 95%-Prognosebereich
# Laufzeit.sim wurde berechnet

# Berechnung und Ausgabe der Quantilwerte
PI = quantile(Laufzeit.sim, prob=c(0.025,0.975))
PI

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 217: 95%-Streubereich für die Anpassungsgüte R²
#lm.2 wurde berechnet

require(car) # Paket car laden

BTD.Laufzeit=Boot(lm.2,
	f = function(mod){summary.lm(mod)$r.squared},
	R=10^4)
# Boot(daten,funktion,anzahl,...) ist Bootstrapping-Funktion
# f gibt die Funktion für die Kennzahl R² an
# hier: R² aus der Zusammenfassung des Modells
# R: Anzahl Simulationsdurchläufe

confint(BTD.Laufzeit, level=.95, type="perc")
# berechnet den Streubereich von BTD.Laufzeit
# level Abdeckbereich
# perc: Perzentil- bzw. Quantil-Methode

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 218: Boxplot
# Simulierte Anpassungsgüten BTD.Laufzeit sind berechnet
boxplot(BTD.Laufzeit$t, pch=8, col="lightgrey", lty=1)
# BTD.Laufzeit$t: simulierte BTD.Laufzeit-Anpassungsgüten
abline(h=c(0.8327,0.9262,0.8744), col="red")
# zeichnet drei horizontale Linien ein

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 218: Zeitreihendiagramm
# Simulierte Anpassungsgüten BTD.Laufzeit sind berechnet
plot(BTD.Laufzeit$t)
# BTD.Laufzeit$t: simulierte BTD.Laufzeit-Anpassungsgüten
abline(h=c(0.8327,0.9262,0.8744), col="red")
# zeichnet drei horizontale Linien ein

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 225: 95%-Streubereich für die Anpassungsgüte R²
# lm.2 wurde berechnet

require(car) # Paket car laden

BTR.Laufzeit=Boot(lm.2,
	f = function(mod){summary.lm(mod)$r.squared},
	R=10^4,
	method="residual")
# Boot(daten,funktion,anzahl,...) ist Bootstrapping-Funktion
# f gibt die Funktion für die Kennzahl R² an
# hier: R² aus der Zusammenfassung des Modells
# R: Anzahl Simulationsdurchläufe
# method wählt die Bootstrap-Methode, "residual": Residuen wie in (31)

confint(BTR.Laufzeit, level=.95, type="perc")
# berechnet den Streubereich von BTR.Laufzeit
# level Abdeckbereich
# perc: Perzentil- bzw. Quantil-Methode

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 225: Boxplot
# Simulierte Anpassungsgüten BTR.Laufzeit sind berechnet
boxplot(BTR.Laufzeit$t, pch=8, col="lightgrey", lty=1)
# BTR.Laufzeit$t: simulierte BTR.Laufzeit-Anpassungsgüten
abline(h=c(0.8430,0.9083,0.8744), col="red")
# zeichnet drei horizontale Linien ein

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 226: Zeitreihendiagramm
# Simulierte Anpassungsgüten BTR.Laufzeit sind berechnet
plot(BTR.Laufzeit$t)
# BTR.Laufzeit$t: simulierte BTR.Laufzeit-Anpassungsgüten
abline(h=c(0.8430,0.9083,0.8744), col="red")
# zeichnet drei horizontale Linien ein

## Kapitel 10 ##
#
# Optimierung und Nachweis

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 236: Zielgrößenoptimierung
# lm.2 wurde berechnet

# Zielgrößenoptimierung
# Wunschfunktion d*_min als Funktion "d.min2" definieren
d.min2=function(y,OG,Ziel,w) {
  ifelse(y>OG, 0, ((OG-y)/(OG-Ziel))^w*100 ) }
# ifelse(Bedingung, A, B): prüft Bedingung für jedes Element
# und gibt A zurück wenn wahr und B wenn falsch

# Rasterwerte erstellen
d.PL=seq(min(PL),max(PL),length=100)
# seq() erstellt eine Sequenz von Werten
# min() liefert das Minimum
# max() liefert das Maximum
# length gibt an aus wie vielen Werte die Sequenz besteht
d.PMa=seq(min(PMa),max(PMa))
d.Abteilungen=seq(min(Abteilungen),max(Abteilungen))
d.Lieferant=levels(Lieferant)
# levels() gibt die Kategorien eines attributiven Merkmals aus
d.Kunde=levels(Kunde)
d.Methode=levels(Methode)
d.Review=levels(Review)
d.Komplexität=levels(Komplexität)

# Rasterwerte in einer Liste speichern
Raster.Liste = list(PL=d.PL, PMa=d.PMa,
	Abteilungen=d.Abteilungen, Lieferant=d.Lieferant,
	Kunde=d.Kunde, Methode=d.Methode,
	Review=d.Review, Komplexität=d.Komplexität)

# alle Kombinationen erzeugen
Raster = expand.grid(Raster.Liste)

# Prognosewerte berechnen und in Spalte "Prognose" anhängen
Raster[, "Prognose"] = c(predict(lm.2, Raster))
# Werte von d*_min berechnen und in Spalte "dmin2" anhängen
Raster[, "dmin2"] = d.min2(Raster$Prognose, OG=50, Ziel=25, w=1)

# Auswahl kurzer Projekte
kurze.Projekte = subset(Raster, Raster$dmin2 > 0)
#  subset() erstellt Auswahl nach Kriterium "Raster-Werte d*_min > 0"
dim(Raster)
dim(kurze.Projekte)
# dim() liefert die Dimensionen, d. h. Anzahl Zeilen (1. Wert) und Spalten (2. Wert)
summary(kurze.Projekte)
# summary() liefert Kennzahlen
Raster[Raster$dmin2==max(Raster$dmin2),]
# zeigt die Einstellungen an mit denen dmin2 maximal ist

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 253: Finden der Kombinationen mit obere Prognosegrenze > 200 Tage
# lm.2 wurde berechnet

# Worst-Case-Wunschfunktion d*_max als Funktion "d.max" definieren
d.max=function(y,UG,Ziel,w) {
  ifelse(y<UG, 0,
		ifelse(y>Ziel, 100, ((y-UG)/(Ziel-UG))^w*100 ))
  }
# ifelse(Bedingung, A, B): prüft Bedingung für jedes Element
# und gibt A zurück wenn wahr und B wenn falsch

# Rasterwerte erstellen
d.PL=seq(min(PL),max(PL),length=100)
d.PMa=seq(min(PMa),max(PMa))
d.Abteilungen=seq(min(Abteilungen),max(Abteilungen))
d.Lieferant=levels(Lieferant)
d.Kunde=levels(Kunde)
d.Methode=levels(Methode)
d.Review=levels(Review)
d.Komplexität=levels(Komplexität)

# Rasterwerte in einer Liste speichern
Raster.Liste = list(PL=d.PL, PMa=d.PMa,
	Abteilungen=d.Abteilungen, Lieferant=d.Lieferant,
	Kunde=d.Kunde, Methode=d.Methode,
	Review=d.Review, Komplexität=d.Komplexität)

# alle Kombinationen erzeugen
Raster = expand.grid(Raster.Liste)

# Obere 99%-Prognosegrenze "OPG" berechnen
OPG = as.data.frame(predict(lm.2, Raster,
	interval="prediction", level=0.98))$upr
# predict(., interval="'prediction"') berechnet zweiseitige Prognosegrenzen
# level=0.98 Anteil innerhalb des zweiseitig begrenzten Prognoseintervalls an
# bei 98% innerhalb liegen 2% außerhalb, mit 1% > OPG
# $upr wählt obere Prognosegrenze (upper prediction limit) für OPG aus

# und in Spalte "OPG" anhängen
Raster[, "Prognosegrenze"] = OPG

# Projekte mit OPG>200 in "lange.projekte" speichern
lange.projekte=subset(Raster, Raster$Prognosegrenze > 200)
summary(lange.projekte)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 254 Einschränkung der Einstellkombinationen auf obere Prognosegrenze < 200 Tage
# Der Datensatz "lange.projekte" wurde erstellt

# Matrixplot für die variablen Merkmale PL, PMa und Abteilungen
require(lattice) # Paket lattice laden

lange.projekte.variabel = subset(lange.projekte, select=c(PL,PMa, Abteilungen))
# Auswahl der variablen Merkmale aus "lange.projekte"
splom (~lange.projekte.variabel)
# Matrixplot für alle variablen Einflüsse
# kaum sicherer Bereich identifizierbar

# Kombinationen der attributiven Merkmale erstellen
werte.attributiv = list(Lieferant=d.Lieferant, Kunde=d.Kunde,
                        Methode=d.Methode, Review=d.Review,
                        Komplexität=d.Komplexität)
kombi = expand.grid(werte.attributiv)

# Platzhalter "Anzahl" definieren, der so viele Stellen hat wie es Kombinationsmöglichkeiten der attributiven Merkmale gibt (hier: 48)
Anzahl=numeric(nrow(kombi))
# nrow() zählt Anzahl Zeilen (number of rows)

# Für alle Kombinationsmöglichkeiten in "kombi" zählen, wie oft (Anzahl) OPG > 200~Tage im Datensatz "lange.projekte" ist
for(i in 1:nrow(kombi)){
	Anzahl[i] = nrow(subset(lange.projekte,
		(Lieferant==kombi$Lieferant[i])
		& (Kunde==kombi$Kunde[i])
		& (Methode==kombi$Methode[i])
		& (Review==kombi$Review[i])
		& (Komplexität==kombi$Komplexität[i])))
	}

# Anfügen der Spalte "Anzahl" an "kombi" und speichern als Datensatz "Häufigkeit"
Häufigkeit=data.frame(cbind(kombi,Anzahl))
# data.frame() erstellt Datenstruktur
# cbind() verbindet Spalten (column bind)

# Auswahl der Kombinationen, in denen nie OPG > 200 bzw. Anzahl(OPG>200)=0 ist
Sicher=subset(Häufigkeit, Anzahl==0)

summary(Sicher)
# Kennzahlen für Datensatz "Sicher"
# kein attributives Merkmal hat bei Projekten mit OPG <= 200 immer dieselbe Einstellung
# tendenziell Merkmal Komplexität am eindeutigsten

# Kombinationen der attributiven Merkmale mit OPG kleiner 200~Tage je Komplexitäts-Level
subset(Sicher, Komplexität=="hoch")
subset(Sicher, Komplexität=="mittel")
subset(Sicher, Komplexität=="niedrig")

## Kapitel 11 ##
#
# Toleranzen

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 265: Test auf Normalverteilung und Wahrscheinlichkeitsnetz
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ_1.CSV) verfügbar gemacht

# Test auf Normalverteilung (Anderson-Darling)
require(nortest) # Paket nortest laden
ad.test(Laufzeit)
# berechnet den Anderson-Darling-Test auf Normalverteilung (ad.test) und gibt die Werte aus

# Wahrscheinlichkeitsnetz
qqnorm(Laufzeit, xlab="Normalverteilungs-Quantile",
	ylab="Laufzeit", main="Wahrscheinlichkeitsnetz", pch=20)
qqline(Laufzeit, col="blue")
# qqnorm zeichnet Wahrscheinlichkeitsnetz für Normalverteilung
# xlab, ylab, main: Beschriftung x-Achse, y-Achse und Titel
# qqline zeichnet Ideallinie (hier: blau)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 271: Toleranzgrenze ohne Normalverteilung
# Daten PLZ_1.CSV sind eingelesen

require(tolerance) # für die Toleranzrechnung muss das Package "tolerance" installiert sein

nptol.int(Laufzeit, alpha=0.05, P=0.99, side=1)
# nptol.int() berechnet verteilungsfreie Toleranzintervalle
# alpha=0.05 entspricht Konfidenz- oder Vertrauensniveau von 95%
# P=0.99 Abdeckung der Laufzeit (99%)
# side=1 berechnet einseitige Toleranzgrenzen

distfree.est(n = length(Laufzeit), P = 0.99, side = 1)
# berechnet die erreichte Konfidenz für 99% Abdeckung bei n=132 Werten

distfree.est(n = length(Laufzeit), alpha=0.05, side = 1)
# berechnet die erreichbare Abdeckung bei n=132 Werten und 95% Konfidenz

distfree.est(P=0.99, alpha=0.05, side = 1)
# berechnet die Mindestanzahl Messwerte für 99% Abdeckung und 95% Konfidenz

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 277: Monte Carlo-Toleranz
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ_1.CSV) verfügbar gemacht
# lm.2 wurde berechnet

Simu=10^4 # Anzahl Simulationen in "Simu" speichern

# Zusammenstellung der Daten für die Monte Carlo-Simulation
sim.PL=abs(rnorm(Simu, mean(PL), sd(PL)))
sim.PMa=ceiling(abs(rnorm(Simu, mean(PMa), sd(PMa))))
sim.Abt=ceiling(abs(rnorm(Simu, mean(Abteilungen),sd(Abteilungen))))
sim.daten = data.frame(Lieferant="ja",Kunde="ja",Methode="SiSi",Review="ja",Komplexität="hoch",PL=sim.PL,PMa=sim.PMa,Abteilungen=sim.Abt)

# Berechnung der simulierten Projektdurchlaufzeiten
Laufzeit.sim=predict(lm.2,sim.daten)
MC.daten=cbind(sim.daten,Laufzeit.sim)

# Boxplot simulierte Laufzeit
boxplot(Laufzeit.sim, pch=8, col="lightgrey", lty=1, data=MC.daten)

# Test auf Normalverteilung (Anderson-Darling) und Wahrscheinlichkeitsnetz
require(nortest) # Paket nortest laden
ad.test(Laufzeit.sim)

qqnorm(Laufzeit, xlab="Normalverteilungs-Quantile",
	ylab="Laufzeit", main="Wahrscheinlichkeitsnetz", pch=20)
qqline(Laufzeit, col="blue")

# Berechnen der 99%-Toleranzgrenze
require(tolerance) # Paket tolerance laden

nptol.int(Laufzeit.sim, alpha=0.05, P=0.99, side=1)
distfree.est(n = length(Laufzeit.sim), P = 0.99, side = 1)

#++++++++++++++++++++++++++++++++++++++++++++++++#
# S. 291: Bootstrap-Toleranz
# Daten PLZ_1.CSV sind eingelesen und mit attach(PLZ_1.CSV) verfügbar gemacht
# lm.2 wurde berechnet

# Einstellwerte für Prognose
x.p = data.frame(Lieferant="ja",Kunde="ja",Methode="SiSi",
	Review="ja",Komplexität="hoch", PL=median(PL),PMa=median(PMa),
	Abteilungen=median(Abteilungen))

# Prognosewert ydach_p
y.p = predict(lm.2,x.p)

# modifizierte Residuen
ri = lm.2$res/sqrt(1-lm.influence(lm.2)$hat) - mean(lm.2$res/sqrt(1-lm.influence(lm.2)$hat))
# lm.2$res Residuen von lm.2
# sqrt() Wurzelfunktion
# lm.influence(lm.2)$hat Hebelwirkungen von lm.2
# mean() Mittelwert

# Einstellwerte für SPM
x.werte = subset(PLZ.1, select=c(PL, PMa, Abteilungen, Lieferant, Kunde, Methode, Review, Komplexität))
# Auswahl der Spalten mit Einstellwerten

Simu=10^4 # Anzahl Simulationen in "Simu" speichern

# Container für "delta.stern" und "y.sim" definieren
delta.stern = NULL
y.sim = NULL

# Werte "delta.stern" und "y.sim" berechnen
for(i in 1:Simu){
	e.stern = sample(ri, size=nrow(PLZ.1), replace=TRUE)
	y.stern = lm.2$fit + e.stern
	lm.2.stern = lm(y.stern ~ PL + PMa + Abteilungen + Lieferant
		+ Kunde + Methode + Review + Komplexität  + I(PMa^2)
		+ PL:PMa + Abteilungen:Methode + Lieferant:Kunde
		+ Kunde:Komplexität + Methode:Review,
		data=cbind(x.werte,y.stern))
	y.p.stern = predict(lm.2.stern,x.p)
	e.p.stern = sample(ri, size=nrow(x.p), replace=TRUE)
	delta.stern[i] = y.p.stern - (y.p+e.p.stern)
	# i-ter Wert für delta.stern
	y.sim[i] = y.p + delta.stern[i]
	# i-ter simulierte Bootstrap-Prognosewert
	}

# Boxplot simulierte Laufzeit
boxplot(y.sim, pch=8, col="lightgrey", lty=1)

# Test auf Normalverteilung (Anderson-Darling) und Wahrscheinlichkeitsnetz
require(nortest) # Paket nortest laden
ad.test(y.sim)

qqnorm(y.sim, xlab="Normalverteilungs-Quantile",
	ylab="Laufzeit", main="Wahrscheinlichkeitsnetz", pch=20)
qqline(y.sim, col="blue")

# Berechnen der 99%-Toleranzgrenze
require(tolerance) # Paket tolerance laden
normtol.int(y.sim, alpha=0.05, P=0.99, side=1)
# normtol.int() berechnet Toleranzgrenzen für normalverteilte Werte


#' paleohydror: A package for implementing published routines in paleohydrologic reconstruction.
#'
#' This package offers several functions and routines for deriving estimates of paleohydrology from field observations of rock outcrops. Data such as grain size are important too.
#'
#' @section paleohydror functions:
#'
#' The functions here make up a mix of tools to calculate and estimate modern suficial processes and back-calculate those processes in ancient rivers.
#'
#' \code{settle} calculates the settling velocity of particles following the formulation by Dietrich (1982).
#'
#' \code{lynds_one} estimates ancient river slope using the first method described by Lynds et al. (2014)
#'
#' \code{lynds_two} estimates ancient river slope using the second method described by Lynds et al. (2014)
#'
#' \code{lynds_three} estimates ancient river slope using the third method described by Lynds et al. (2014)
#'
#' \code{xset2H} estimates ancient river dune heights based on cross-set thicknesses. Methods from Leclair and Paola.
#'
#' \code{H2h} estimates ancient river depths based on dune heights. Methods from Bradley and Venditti.
#'
#' \code{xset2depthSimple} estimates ancient river depths directly from cross-set thicknesses using the simplest assumptions. Methods from Leclair, Paola, and Bradley and Venditti.
#'
#' \code{azStringConvert} Azimuth conversion for 'quadrant' based strike/trend measurements.
#'
#' \code{ancient_1} Estimating sediment flux in ancient rivers following Mahon + McElroy (2018).
#'
#' \code{modern_1} Estimating sediment flux in modern rivers if bedform height is known following Mahon + McElroy (2018).
#'
#' \code{modern_2} Estimating sediment flux in modern rivers if bedform length is known following Mahon + McElroy (2018).
#'
#' \code{bedform_velocity} Estimating bedform migration rate as a function of reach-averaged slope.
#'
#' \code{bedform_bedload} Estimating bedload as a function of bedform height and migration rate. After Simons et al. (1965)
#'
#' \code{height_length} Estimating bedform height if bedform length is known.
#'
#' \code{trampush_slp} estimates paleoslope using an empirical relationship with median bedload grain size and bankfull flow depth from Trampush (2014).
#'
#'
#'
#'
#'
#' @docType package
#' @name paleohydror
NULL


########################### BayesKin ###########################
## Bayesian estimates of rigid body kinematics
## Andy Pohl
## UofC - Faculty of Kinesiology

## Written by: Andy Pohl
## UofC - Faculty of Kinesiology
## June-Dec 2020
## Revision 1: June 2021
################################################################

##################### example.r  ###################
## Performs analysis comparing Bayesian to Least squares approaches for
## 3 link kinematic chains.
################################################################
rm(list = ls())
WORKING_DIR = "" # Replace with the location of the BayesKin/src directory on the local PC.

setwd(WORKING_DIR)
INIT_TYPE = 'ls_est' # specify the type of initial values to be used for MCMC sampling - either 'true_vals', 'ls_est', 'random
source('library.r') # Retrieve function library
set.seed(1)  # Set seed for reproducibility

## 1) Specify parameters
n.links = 3                             # Number of links.
seg.length = c(0.45, 0.35, 0.25)        # Length of segment
r_true = c(0.07, 0.03)                  # Origin location in m.
theta_true = c(-55, -110, -10)          # Rotation angle in deg.
sigma_true = 1.5/1000                   # Measurement noise in m.
true_vals = c(r_true = r_true, theta_true = theta_true, sigma_true = sigma_true)

# Generate posture
links = list(gen_link(seg.length = seg.length[1],
                      plate.center = 0.7*seg.length[1]),
             gen_link(seg.length = seg.length[2],
                      plate.center = 0.5*seg.length[2]),
             gen_link(seg.length = seg.length[3],
                      plate.center = 0.5*seg.length[3]))
posture = gen_posture(links, r = r_true, theta = theta_true)

# posture is a list with entries $r containing the location of the origin, $J containing the location of each joint
# where J[[1]] is the origin and J[[4]] is the termination of the kinematic chain. $alpha gives the actual position markers

# Generate observation
y = gen_obs(posture, sigma_true)
# y is a list of length nlinks with each list item containing a 2xnmarkers array of observed marker locations in the
# global frame.

plot_system(posture, y=y) # Provides a visualisation of the pose with observed markers in orange and true positions in blue

## 2) Apply LS or Bayesian models
#Compute LS solution.
LS_result = LS_soln(y, links,
                    inits = c(r_true, theta_true, sigma_true),
                    init_type = 'true_vals')

LS_result
# The output of LS_result contains estimates of r and theta_i given by r.hat, theta.hat and $sigma.hat
# along with 95% confidence intervals for each parameter in $intervals.  $time denotes the computation time of the LS solution
# $value provides the value of the cost function at the LS estimate.

# Compute a Bayesian solution
Bayes_result = Bayes_soln(y=y,
                          links = links,
                          mdlfile = './BayesModel_p3.jags', # choose what model to use by specifying the appropiate .jags file here.
                          init_type = INIT_TYPE,
                          true_vals = true_vals,
                          ls_est = c(LS_result$r.hat, LS_result$theta.hat, LS_result$sigma.hat))
# Bayes_result provides a list with $fit being a 'coda' object containing the MCMC samples for the fitted model
# $time provides the computational
summary(Bayes_result$fit) # provides posterior means for each pose parameter along with their 95% credible interval (via 2.5 and 97.5 quantiles)
plot(Bayes_result$fit) # provides traceplots and density estimates for each parameter.


#### covidWBE.r
#### Nick Crosbie, May 2020
#### source("./bin/covidWBE.r")

library(EnvStats)

# WASTEWATER CATCHMENT (calculate dry weather flow in millilitres per day)
catchmentPop <- 10^4 # number of people in catchment
dryWeatherFlowPerPerson <- 2.12799e-4 # dry weather flow contributed by each person, in ** megalitres ** per day (average derived from all participating ColoSSoS WWTP catchments)
dryWeatherFlow_MLD <- catchmentPop * dryWeatherFlowPerPerson # catchment dry weather flow, in ** megalitres ** per day
dryWeatherFlow_mLD <- dryWeatherFlow_MLD * 1e9 # catchment dry weather flow, in ** millilitres ** per day

# SARS-CoV-2 GENOMES SHED PER DAY TO CATCHMENT BY DEFECATION (number of genomes)
modeShed <- 10^3 # mode number of genomes shed in faecies by an infected person (genomes per millilitre of faecies)
minShed <- 10^2 # min number of genomes shed in faecies by an infected person (genomes per millilitre of faecies)
maxShed <- 10^7 # max number of genomes shed in faecies by an infected person (genomes per millilitre of faecies)

defVol <- 200 # volume of faecies defacated per day by an individual, in millilitres (no distinction made between volume defecated by infected and non-infected individuals)
numberShedding <- 1 # number of people shedding in catchment
defVolInfCat <- defVol * numberShedding #  combined volume of faecies defacated by shedders per day, in millilitres

modeShedCat <- modeShed * defVolInfCat # mode number of genomes shed per day to catchment by infected population
minShedCat <- minShed * defVolInfCat # minimum number of genomes shed per day to catchment by infected population
maxShedCat <- maxShed  * defVolInfCat # maximum number of genomes shed per day to catchment by infected population

# TRIANGULAR DISTRIBUTION OF SARS-CoV-2 GENOMES SHED PER DAY TO CATCHMENT BY DEFECATION (number of genomes)
triagShedCat <- simulateVector(n = 10000, distribution = "tri", param.list = list(min = minShedCat, mode = modeShedCat, max = maxShedCat),
sample.method = "LHS", seed = 47)

pdfPlot(distribution = "tri", param.list = list(min = minShedCat, mode = modeShedCat, max = maxShedCat), n.points = 10000)

# SARS-CoV-2 CONCENTRATION AT POINT OF WASTEWATER SUBSAMPLING (genomes per mL)
catchmentDilution <- defVolInfCat / dryWeatherFlow_mLD
wastewaterConc <- triagShedCat * catchmentDilution # genomes per mL of catchment wastewater, ** assuming fully mixed catchment **

# plot(ecdf(wastewaterConc))

# SARS-CoV-2 CONCENTRATION OF FINAL CONCENTRATED PREPARATION
concFactor <- 4  # concentration factor from point of wastewater sampling to final concentrated preparation
finalPrepConc <- wastewaterConc * concFactor # virus concentration prior to subsampling for PCR (genomes per millilitre)

#plot(ecdf(finalPrepConc))

# SARS-CoV-2 GENOMES PER PCR REACTION (number of genomes)
finalConcVol <- 2 # volume of sample prior to subsampling for PCR reaction, in millilitres
genomesFinalPrep <- finalPrepConc * finalConcVol # number of genomes contained in the final prep (step immediately prior to PCR)

templateVol <- 0.005 # volume in which the final preparation is resuspended prior to pipetting to PCR reaction
volRxn <- 0.05 # volume of one PCR reaction, in millilitres (i.e. 50 microlitres)
genomesRxn <- genomesFinalPrep * (templateVol/volRxn) # genomes per reaction
LOD <- 10 # PCR limit of detection as genomes per reaction

n <- 10000 # number of wastewater samples analysed for SARS-CoV-2
detects <- sum(genomesRxn > LOD) # number of SARS-CoV-2 detects
trueDetectProportion <- 0.90 # proportion of detects that are true positives
percentRealDetects <- ((detects * trueDetectProportion) / n) * 100 # percentage of samples where SARS-CoV-2 is detected

print(percentRealDetects)

# plot(ecdf(genomesRxn))


#==============================================================================
#	Functions used for MESS.
#==============================================================================

#------------------------------------------------------------------------------
#'	(Internal) Calculate distance between test and training data using MESS
#'
#'	This function calculate multivariate environmental similarity surface
#'	(MESS, Elith, Kearney and Phillips 2010) for each point in test data.
#'
#'	@param data.train a data.frame containing training data.
#'	@param data.test a data.frame containing test data.
#'	@param na.rm a logical indicating ignorance of NA.
#'
#'	@section References:
#'	Elith, J., M. Kearney, and S. Phillips. 2010.
#'	The art of modelling range-shifting species.
#'	Methods in Ecology and Evolution 1:330-342.
#------------------------------------------------------------------------------
calculate.mess <- function(data.train, data.test, na.rm = TRUE) {
	# Prepare matrix for the result.
	numeric.columns <- colnames(data.test)[sapply(data.test, is.numeric)]
	similarity <- matrix(
		NA, nrow = nrow(data.test), ncol = length(numeric.columns)
	)
	colnames(similarity) <- numeric.columns
	# Iterate over numeric columns.
	for (i in numeric.columns) {
		# min_i
		min.i <- min(data.train[[i]], na.rm = na.rm)
		# max_i
		max.i <- max(data.train[[i]], na.rm = na.rm)
		# f_i for all p_i
		smaller.fraction <- sapply(
			data.test[[i]],
			function(x) mean(data.train[[i]] < x, na.rm = na.rm) * 100
		)
		# Similarity: f_i = 0
		case_0 <- (data.test[[i]] - min.i) / (max.i - min.i) * 100
		# Similarity: 0 < f_i <= 50
		case_0_50 <- 2 * smaller.fraction
		# Similarity: 50 <= f_i < 100
		case_50_100 <- 2 * (100 - smaller.fraction)
		# Similarity: f_i = 100
		case_100 <- (max.i - data.test[[i]]) / (max.i - min.i) * 100
		similarity[, i] <- ifelse(
			smaller.fraction == 0, case_0,
			ifelse(
				smaller.fraction <= 50, case_0_50,
				ifelse(smaller.fraction < 100, case_50_100, case_100)
			)
		)
	}
	return(apply(similarity, 1, min))
}

#------------------------------------------------------------------------------
#'	Create a function calculate MESS of a group.
#'
#'	This function creates a function which calculate aggregated MESS for a
#'	group of points.
#'
#'	@param columns
#'		names of columns or index of columns used for calculation of MESS.
#'	@param aggregate.fun
#'		a function used for aggregation of values of MESS of a group.
#'		Functions like \code{mean}, \code{median}, \code{max} and \code{min}
#'		as well as other functions which accept vector of values and return
#'		single value can be used.
#'	@param na.rm
#'		logical indicating whether NA values should be ignored during
#'		calculation of MESS.
#'	@param ...
#'		other arguments passed for \code{aggregate.fun}.
#'
#'	@export
#------------------------------------------------------------------------------
mess <- function(columns = NULL, aggregate.fun = mean, na.rm = TRUE, ...) {
	f <- function(data.train, data.test) {
		if (!is.null(columns)) {
			data.train <- data.train[columns]
			data.test <- data.test[columns]
		}
		return(
			aggregate.fun(calculate.mess(data.train, data.test, na.rm), ...)
		)
	}
	return(f)
}

#==============================================================================
#	Functions and data used for geographic distance.
#==============================================================================

#------------------------------------------------------------------------------
#'	(Internal) Parameters for several earth ellipsoids.
#------------------------------------------------------------------------------
ELLIPSOIDS = list(
    grs80 = list(
        semi.major.axis.m = 6378137,
        semi.minor.axis.m = 6356752.3141403561,
        inverse.flattening = 298.25722210100002
	),
    wgs84 = list(
        semi.major.axis.m = 6378137,
        semi.minor.axis.m = 6356752.3142451793,
        inverse.flattening = 298.25722356300003
	),
    bessel1841 = list(
        semi.major.axis.m = 6377397.1550000003,
        semi.minor.axis.m = 6356078.9628181886,
        inverse.flattening = 299.15281279999999
	)
)

#------------------------------------------------------------------------------
#'	(Internal) Convert degree to radian.
#'
#'	@param x values in degree.
#------------------------------------------------------------------------------
deg2rad <- function(x) {
	return(x / 180 * pi)
}

#------------------------------------------------------------------------------
#'	(Internal) Find parameters for the Vincenty's formulae.
#'
#'	@param f
#'		flattening of the ellipsoid.
#'	@param L
#'		difference in longitude of two points.
#'	@param U1
#'		reduced latitude (latitude on the auxiliary sphere) of point 1.
#'	@param U2
#'		reduced latitude (latitude on the auxiliary sphere) of point 2.
#'	@param threshold
#'		threshold difference to determine convergence.
#'		The value of 1e-12 produces precision of 0.06mm.
#'	@param maxit
#'		maximum number of iteration to test convergence.
#------------------------------------------------------------------------------
find.vincenty.parameters <- function(f, L, U1, U2, threshold, maxit) {
	lambda.prev <- lambda <- L
	for (i in 1:maxit) {
		sin.sigma <- sqrt(
			(cos(U2) * sin(lambda)) ^ 2
			+ (cos(U1) * sin(U2) - sin(U1) * cos(U2) * cos(lambda)) ^ 2
		)
		cos.sigma <- sin(U1) * sin(U2) + cos(U1) * cos(U2) * cos(lambda)
		sigma <- atan2(sin.sigma, cos.sigma)
		sin.alpha <- cos(U1) * cos(U2) * sin(lambda) / sin.sigma
		cos2.alpha <- 1 - sin.alpha ^ 2
		cos.2sigma.m <- cos.sigma - (2 * sin(U1) * sin(U2) / cos2.alpha)
		C <- f / 16 * cos2.alpha * (4 + f * (4 - 3 * cos2.alpha))
		lambda <- (
			L + (1 - C) * f * sin.alpha * (
				sigma + C * sin.sigma * (
					cos.2sigma.m + C * cos.sigma * (
						-1 + 2 * (cos.2sigma.m ^ 2)
					)
				)
			)
		)
		if (all(abs(lambda - lambda.prev) <= threshold)) {
			break
		}
		lambda.prev <- lambda
	}
	if (i == maxit) {
		stop(
			"Couldn't determine distance(s).\n",
			"Try increasing the value of 'maxit'."
		)
	}
	result <- list(
		sigma = sigma, sin.sigma = sin.sigma, cos.sigma = cos.sigma,
		cos2.alpha = cos2.alpha, cos.2sigma.m = cos.2sigma.m
	)
	return(result)
}

#------------------------------------------------------------------------------
#'	(Internal) Calculate distance using the Vincenty's formulae.
#'
#'	@param a
#'		semi major axis length in m.
#'	@param b
#'		semi minor axis length in m.
#'	@param lon1
#'		vector of longitude (x) of point 1 in radian.
#'	@param phi1
#'		vector latitude (y) of point 1 in radian.
#'	@param lon2
#'		vector of longitude (x) of point 2 in radian.
#'	@param phi2
#'		vector of latitude (y) of point 2 in radian.
#'	@param threshold
#'		threshold difference to determine convergence.
#'		The value of 1e-12 produces precision of 0.06mm.
#'	@param maxit
#'		maximum number of iteration to try before convergence.
#'
#'	@section References:
#'		Vincenty, T. (1975)
#'		Direct and inverse solutions of geodesics on the ellipsoid with
#'		application of nested equations. Survey Review 23:88-93.
#------------------------------------------------------------------------------
vincenty.distance <- function(
	a, b, lon1, phi1, lon2, phi2, threshold = 1e-12, maxit = 1000
) {
	# Prepare parameters.
	f <- (a - b) / a
	U1 <- atan((1 - f) * tan(phi1))
	U2 <- atan((1 - f) * tan(phi2))
	L <- lon2 - lon1
	# Find the Vincenty's formulae's parameters.
	params <- find.vincenty.parameters(f, L, U1, U2, threshold, maxit)
	# Calculate distances.
	mu2 <- params$cos2.alpha * (a ^ 2 - b ^ 2) / b ^ 2
	A <- 1 + mu2 / 16384 * (4096 + mu2 * (-768 + mu2 * (320 - 175 * mu2)))
	B <- mu2 / 1024 * (256 + mu2 * (- 128 + mu2 * (74 - 47 * mu2)))
	delta.sigma <- B * params$sin.sigma * (
		params$cos.2sigma.m
		+ B / 4 * (
			params$cos.sigma * (-1 + 2 * params$cos.2sigma.m ^ 2)
			- B / 6 * (
				params$cos.2sigma.m * (-3 + 4 * params$sin.sigma ^ 2)
				* (-3 + 4 * params$cos.2sigma.m ^ 2)
			)
		)
	)
	s <- b * A * (params$sigma - delta.sigma)
	return(s)
}

#------------------------------------------------------------------------------
#'	Create a function calculates geographic distance.
#'
#'	@param x.name
#'		column name of longitude.
#'		Data should be stored in decimal degree.
#'	@param y.name
#'		column name of latitutde.
#'		Data should be stored in decimal degree.
#'	@param ellipsoid
#'		name of earth ellipsoids, can be "grs80", "wgs84" or "bessel1841".
#'	@param method
#'		the method used for calculation of distance.
#'		Currently, only the method using the Vincenty's formulae is
#'		implimented.
#'	@param threshold
#'		threshold difference to determine convergence.
#'		The value of 1e-12 produces precision of 0.06mm.
#'	@param maxit
#'		maximum number of iteration to try before convergence.
#'
#'	@section Details:
#'		\url{https://en.wikipedia.org/wiki/Vincenty's_formulae}.
#'
#'	@export
#------------------------------------------------------------------------------
geographic.distance <- function(
	x.name, y.name, ellipsoid = c("grs80", "wgs84", "bessel1841"),
	method = c("vincenty"), threshold = 1e-12, maxit = 10000
) {
	ellipsoid <- match.arg(ellipsoid)
	a <- ELLIPSOIDS[[ellipsoid]]$semi.major.axis.m
	b <- ELLIPSOIDS[[ellipsoid]]$semi.minor.axis.m
	fun <- function(data.train, data.test, na.rm = TRUE) {
		phi1 <- deg2rad(mean(data.train[y.name], na.rm = na.rm))
		phi2 <- deg2rad(mean(data.test[y.name], na.rm = na.rm))
		lon1 <- deg2rad(mean(data.train[x.name], na.rm = na.rm))
		lon2 <- deg2rad(mean(data.test[x.name], na.rm = na.rm))
		d <- vincenty.distance(a, b, lon1, phi1, lon2, phi2, threshold, maxit)
		return(d)
	}
	return(fun)
}

#==============================================================================
#	Functions used for forecast horizon.
#==============================================================================

#------------------------------------------------------------------------------
#'	(Internal) Calculate distance between training and test datasets.
#'
#'	@param fold.index
#'		an integer representing index of the fold for which the distance
#'		between test and training datasets is calculated.
#'	@param data
#'		a data.frame containing explanatory variable(s).
#'	@param cv.group
#'		a vector of integer representing grouping of observation.
#'	@param distance.fun
#'		a function calculating distance between test and training datasets.
#'		It should accept two data.frames in the following form and calculate
#'		distance between them: \code{distance.fun(training.data, test.data)}.
#'		Functions produced by \code{\link{geographic.distance}} and
#'		\code{\link{mess}} can be used.
#------------------------------------------------------------------------------
calculate.distance.between.train.and.test <- function(
	fold.index, data, cv.group, distance.fun
) {
	data.train <- data[cv.group != fold.index, , drop = FALSE]
	data.test <- data[cv.group == fold.index, , drop = FALSE]
	return(distance.fun(data.train, data.test))
}

#------------------------------------------------------------------------------
#' (Experimental) Draw a forecast horizon graph.
#'
#'	Draw a forecast horizon graph using result of the cross validation.
#'	This function is experimental.
#'
#'	@param object
#'		a \code{cv.models} object.
#'	@param metric.name
#'		a character representing name of metrics to be drawn.
#'	@param distance.fun
#'		a function which calculates distance between training and test dataset.
#'		It should accept two data.frames in the following form and calculate
#'		distance between them: \code{distance.fun(training.data, test.data)}.
#'		Functions produced by \code{\link{geographic.distance}} and
#'		\code{\link{mess}} can be used.
#'	@param index
#'		an index of candidate model in the \code{cv.models} object.
#'	@param ylab
#'		label of Y axis.
#'	@param xlab
#'		label of X axis.
#'	@param draw
#'		logical indicating whether the plot is draw.
#'		If FALSE, this function only returns calculated results and draw
#'		nothing.
#'	@param ...
#'		graphical parameters passed to plot function.
#'
#'	@return
#'	a data.frame having distance between training data and corresponding
#'	performance measure.
#'
#'	@export
#------------------------------------------------------------------------------
forecast.horizon <- function(
	object,
	metric.name = ifelse(
		object$adapter$model.type == "regression", "q.squared", "mcc"
	),
	distance.fun = mess(), index = 1, ylab = metric.name,
	xlab = deparse(substitute(distance.fun)), draw = TRUE, ...
) {
	# Extract explanatory variables.
	data <- object$adapter$data[object$adapter$x.names()]
	# Extract index.
	cv.group <- object$cv.results[[index]]$cv.group
	# Extract metric.
	object$aggregate.method = "folds"
	metrics <- cv.metrics(object, list(object$cv.results[[index]]$fits))[[1]]
	# Calculate distance between training and test data.
	distance <- sapply(
		1:object$folds, calculate.distance.between.train.and.test,
		data = data, cv.group = cv.group, distance.fun = distance.fun
	)
	graphics::plot(
		distance, metrics[, metric.name], ylab = ylab, xlab = xlab, ...
	)
	invisible(cbind(data.frame(distance = distance), metrics))
}