Go back to Flu Mortality


library(bbmle)

library(deSolve)

data1 = c(106, 121, 136, 156, 183, 248, 279, 276, 239, 185, 160, 187, 150, 193, 153, 153, 138, 143, 119)

t1 = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)

base1 = c(105.1240, 106.3563, 107.5804, 108.7790, 109.9351, 111.0325, 112.0557, 112.9902, 113.8230, 114.5424, 115.1383, 115.6027, 115.9291, 116.1133, 116.1530, 116.0481, 115.8005, 115.4142, 114.8952)

model_SIR = function(t, theta) {

  SIR = function(Time, State, Pars) {
  with(as.list(c(State, Pars)), {

      DecreaseS = -1 * beta * S * I / N
      DecreaseI = -1 * alpha * I

      dS = DecreaseS
      dI = -1 * DecreaseS + DecreaseI

      return(list(c(dS, dI)))
      })
  }  

  with(as.list(theta), {
    
  state1 = c(S = N - I1, I = I1)  
  pars1 = c(beta = beta1, alpha = alpha1, N = N)

  state2 = c(S = N - I2, I = I2)  
  pars2 = c(beta = beta2, alpha = alpha2, N = N)
    
  out1 = ode(y = state1, times = t, func = SIR, parms = pars1,     method = 'ode45')

  out2 = ode(y = state2, times = t, func = SIR, parms = pars2,     method = 'ode45')

      return(cbind(-diff(out1[,"S"]), -diff(out2[,"S"])))
  })

}

loglik_negbin = function(theta, data, mean) {

  # for negative bimonial, mean = r p /(1-p)
  r = theta[["r"]];
  # if r < 0, return a tiny likelihood
  if (r < 0)
      return(-1e10)
  sum(dnbinom(x=data, size=r, mu=mean, log=TRUE))

}

loglik_poisson = function(theta, data, mean) {

  sum(dpois(x=data, lambda=mean, log=TRUE))

}

SIR_fit_given_logL = function(times, data, base, theta0, model, logL) { # construct a general negative log-likelyhood function

  L <- function()
  {
      # reconstruct the vector of named pairs of
      # parameters from the list of arguments
      l=length(theta0)
      theta=c()
      vars=names(theta0)
    
      for (i in 1:l) {
          item=c(x=get(vars[i]))
          names(item) <- vars[i]
          theta <-c(theta, item)
      }
    
      l = model(times, theta)
    
      #"base" is the vector of baseline values
      mean = l[,1] + l[,2] + base
    
      # compute the negative log-likelihood
      L = -logL(theta, data, mean)
      # if not a number, return a very small likelihood
      if (is.na(L)) return(1e10)
      return(L)
  }

# replace the input arguments of L by the list of parameters formals(L)←as.list(theta0) # mle2 # sometimes confint may find a better solution. # In this case we need to refit the model with the better # solution as a starting paoint, because the parameter # names in the returned better fit can be wrong fit = mle2(L, method = “BFGS”, start = as.list(theta0), control = list(maxit = 1e6*length(theta0))) # fit = mle2(L, method = “Nelder-Mead”, start = as.list(theta0), control = list(maxit = 1e6*length(theta0), ndeps = 1e-4, reltol = 1e-10)) # if there is only one parameter to be fitted # the returned confidence interval is a vector # change it to a matrix return(fit) }

SIR_fit = function(times, data, base, theta0, model) {

  # we start with negative binomial
  # if theta0 contains no r,

  if (is.na(theta0['r']))
      theta0 = c(theta0, r = 10000)
    
  while (TRUE)
  {
      no_r = is.na(theta0['r']);
    
      if (!no_r)
      {
           p = SIR_fit_given_logL(times, data, base, theta0, model, loglik_negbin)
         
           print(p)
      
       }
         
      # if the fitted shape parameter r is too large (> 1000)
      # then it is approximately poisson
      # in this case we use poisson
    
      r1 = coef(p)["r"]
    
      if (no_r || r1[["r"]] > 1000) {
          # we need to remove r from theta
          if (!no_r) {
              old_theta0 = coef(p)
              theta0 = c()
              for (i in 1:length(old_theta0))
                  if (names(old_theta0[i]) != 'r')
                      theta0 = c(theta0, old_theta0[i])
          }
          p = SIR_fit_given_logL(times, data, base, theta0, model, loglik_poisson)
        
          print(p)
      }
    
  conf = confint(p)

  if(is.vector(conf))
  {
      conf = matrix(conf, nrow = 1)
  }

  if(is.matrix(conf))
  {
      break
  }

  theta0 = coef(conf)
  names(theta0) = names(coef(p))
  print(theta0)
  if (is.na(theta0['r']))
      theta0 = c(theta0, r = 10000)

  }

  return(list(fit=p, conf = conf, r=coef(p)["r"]))

}

c = SIR_fit(c(0:19), data1, base1, c(beta1 = 0.3, alpha1 = 0.2, N = 1377, I1 = 1, beta2 = 0.3, alpha2 = 0.2, I2 = 1), model_SIR)

print©

aicc = AICc(c"fit", nobs = length(data1))

print(aicc)