Está en la página 1de 46

Análisis bioestadístico con modelos de

regresión en R

09/2014. Javier Seoane, Carlos P. Carmona, Rocío Tarjuelo y Aimara Planillo.

Modelos truncados e inflados por ceros.


Índice

1. Introducción
2. Modelos truncados por ceros

2a. Fundamentos matemáticos

2b. Análisis exploratorio de datos

2c. Construcción del modelo

2d. Ajuste del modelo

2e. Validación del modelo

2f. Interpretación del modelo

2g. Ejercicio breve

3. Modelos inflados por ceros

3a. Modelos inflados y alterados

3b. Modelos en dos partes

3b1. Poisson

3b2. Binomial Negativa

3c. Modelos inflados

3c1. Fundamentos

3c2. Ejemplo
En esta sesión vamos a usar estos paquetes: ggplot2, VGAM, gridExtra, lattice, pscl,
lmtest, MASS. Asegúrate de tenerlos instalados (ya sabes:
install.packages(c("ggplot2", "VGAM", "gridExtra", "lattice","pscl",
"lmtest", "MASS"))

Introducción

En esta sesión vamos a tratar con dos casos especiales que pueden aparecer cuando
trabajamos con conteos. Aunque ambos casos son fundamentalmente diferentes, tienen
un mismo elemento en común: el 0. Comenzaremos hablando de los modelos que no
permiten que la variable respuesta sea 0 (Zero truncated models), y que por lo tanto
nunca predicen un valor de 0 para ella. Posteriormente pasaremos a los modelos
inflados por ceros (Zero inflated models), en los que, por algún motivo, hay más
observaciones con un valor 0 de las que cabría esperar de acuerdo a una distribución de
Poisson o binomial negativa.

Modelos truncados por ceros

Comencemos mostrando algunos ejemplos de este tipo de datos:

 encuestas en las que se preguntamos a participantes el número de veces que


participan en una actividad. Por ejemplo, i) el número de veces por año que un
visitante de un parque visita ese parque; ii) el número de veces que un paciente
ha estado hospitalizado; iii) el número de delitos por los que ha sido condenada
una persona que está en la carcel; iv) el número de veces hemos fotografiado a
un individuo con una cámara trampa; v) el número de veces que un conductor
tuvo que hacer el exámen práctico.
 datos que por su propia naturaleza no pueden tomar el valor de 0. Por ejemplo, i)
el número de individuos que forman un grupo; ii) el tiempo mediano de
germinación de un conjunto de semillas; iii) el número de días que un paciente
pasa hospitalizado; iv) el número de idiomas que habla una persona.

Como ya hemos visto anteriormente, para datos que toman valores enteros y no
negativos, se utilizan la distribución de Poisson y la Binomial negativa. En la regresión
de Poisson asumimos que la VR se distribuye según una función de Poisson con un
parámetro “mu” μ

(que es tanto la media como la varianza). El problema es que la distribución de Poisson


no excluye los ceros, es decir, predice valores de 0 para la VR, especialmente cuando
los valores de μ

son bajos:

par (mfrow=c(2,3))

muCasos <-c(2,3,4,5,8,15)

for (i in muCasos){
datosPoissonAux <-rpois(1000, lambda=i) #Creo 1000 observaciones
provenientes de una distribución de Poisson con mu=i (en la función
rpois, llaman lambda a mu).
cortes <- seq(from=min(datosPoissonAux)-0.1,
to=max(datosPoissonAux)+0.9, by=1)
h <- hist(datosPoissonAux, plot = FALSE,breaks=cortes)
colores <- ifelse(h$breaks<0.9, "red", "grey80")
plot(h, col=colores, main=bquote(mu == .(i)))
}

Por lo tanto, si μ

es pequeño, pero nuestra variable respuesta no puede tomar el valor 0, es bastante


probable que un modelo con distribución de Poisson (o Binomial Negativa) no funcione
adecuadamente, porque predecirá muchos ceros. En cambio, cuando μ

es grande (como en el último panel de la figura anterior), usar un modelo que no elimine
la posibilidad de predecir ceros no supone un gran problema. Los modelos truncados
por ceros simplemente reparten la probabilidad de que la VR sea 0 de acuerdo a una
distribución de Poisson (las barras de color rojo en la figura), entre todos los demás
valores posibles. Veamos como se hace esto.

¿Y cómo se eliminan los ceros?

Esta sección puede parecer complicada, pero en realidad es muy sencilla.


Vamos a ello. Recordemos que la función de distribución de probabilidad de
Poisson es:

f(yi;μi|yi≥0)=μyi e−μiyi!
Con esta función podemos estimar la probabilidad de que nuestra variable
respuesta tome un valor yi

, sabiendo que sigue una distribución de Poisson con media μi

Veamos un ejemplo: ¿Cuál es la probabilidad de observar un valor de 2 para


nuestra VR, si sabemos que se distribuye de acuerdo a una distribución de
Poisson con media 2? ¿y la de que VR sea 0?

media<- 2
observado<- c(2, 0)
nuestroPoisson<- function(mu, observed){
prob<- ((mu^observed)*(exp(-mu))) / factorial(observed)
return(prob)
}
nuestroPoisson(mu=media,observed=observado)
## [1] 0.2707 0.1353
##Por supuesto, existe una función en R que calcula estas
probabilidades:
dpois(x=c(2,0), lambda=2)
## [1] 0.2707 0.1353

En los modelos sin ceros, excluimos la posibilidad de que la VR tome el valor 0


simplemente dividiendo las probabilidades del resto de valores posibles por [1 -
prob(0)]. Así pues, sustituyendo en la ecuación anterior, podemos calcular la
probabilidad de que VR sea 0:

f(0;μi)=μ0 e−μi0!=e−μi
;

recuerda: 0! = 1 ;-)

con esto, podemos recalcular las probabilidades del resto de valores:

f(yi;μi|yi>0)=μyi e−μi(1−e−μi)yi!
Siguiendo con nuestro ejemplo anterior, podemos recalcular la probabilidad de
que VR=2, sabiendo que el 0 “no vale”:

media<- 2
observado<- 2

prob2<- dpois(x=2, lambda=2)


prob0<- dpois(x=0, lambda=2)

prob2sin0<- prob2/(1-prob0)
prob2sin0
## [1] 0.313
#Es decir, al excluir el 0, el resto de valores son más probables.

Así, los modelos Poisson truncados por ceros son iguales a los glm con errores
de Poisson que hemos visto hasta ahora, con la diferencia de que utilizan
distribuciones de probabilidad en las que se eliminan los ceros y se reajustan
las probabilidades del resto de valores. Como ya dijimos antes, siguiendo el
ejemplo de los histogramas, se reparte la barra roja entre todas las demás –por
eso, cuando μ

es grande, la porción a repartir es muy pequeña y no vale la pena sustituir un


modelo de Poisson por uno truncado por ceros; de hecho, como es muy raro
que se predigan valores negativos, tampoco sale tan a cuenta hacer una
regresión de Poisson en lugar de una normal.

En caso de que, en lugar de una distribución de Poisson, estuviéramos usando


una Binomial Negativa, el procedimiento seria similar.
Manos a la obra: modelos truncados por ceros

Vamos a usar una base de datos para analizar los factores que explican la duración de la
estancia de los pacientes en un hospital. Comencemos cargando y explorando un poco
los datos:

hospital<-read.table(paste(raiz,"Datos/hospital.txt",sep=""),header=T)
str(hospital)
## 'data.frame': 1493 obs. of 4 variables:
## $ stay: int 4 9 3 9 1 4 10 3 5 6 ...
## $ age : int 4 4 7 6 7 5 8 7 4 4 ...
## $ hmo : int 0 1 1 0 0 0 0 0 0 0 ...
## $ died: int 0 0 1 0 1 1 1 1 0 0 ...
head(hospital)
## stay age hmo died
## 1 4 4 0 0
## 2 9 4 1 0
## 3 3 7 1 1
## 4 9 6 0 0
## 5 1 7 0 1
## 6 4 5 0 1
tail(hospital)
## stay age hmo died
## 1488 52 4 0 0
## 1489 14 4 0 0
## 1490 8 4 0 1
## 1491 59 2 0 0
## 1492 63 4 0 0
## 1493 32 6 0 0

La variable respuesta que nos interesa es stay, que es el número de días que los
pacientes permanecen hospitalizados. Una vez que un paciente es ingresado, se
contabiliza el primer día, por lo que esta variable nunca vale 0; empieza a contar en 1:

plot(table(hospital$stay))

#Vemos que N_days nunca vale 0

Vamos a tratar de predecir el número de días en función de las siguientes variables


explicativas:

 age, el grupo de edad al que pertenece el paciente. Varía entre 1 y 9.


 hmo, indica si el paciente tiene seguro médico (1) o no (0).
 died, indica que el paciente falleció en el hospital.

#vamos a decirle a R que los factores son factores :)


hospital$hmo<- factor(hospital$hmo)
hospital$died<- factor(hospital$died)

Lo primero, como siempre, es explorar los datos. Aprovechando la oportunidad, vamos


a probar un paquete muy útil para hacer gráficos, ggplot2.

library(ggplot2)
library(gridExtra) #Habría que instalarlas si no están, Ya sabes;
install.packages()
## Loading required package: grid
#En ggplot, las figuras se hacen de una manera un poco distinta a lo
que hemos visto hasta ahora, creando primero una "capa base", a la que
después se le van añadiendo distintas capas. En este caso vamos a
crear:
#1. Capa base, que indica los datos que vamos a usar, y los ejes
ggplot(hospital, aes(factor(age), stay)) +
#2. Capa con violinplots (muy útiles para ver como se distribuyen las
observaciones)
geom_violin() +
#3. capa con los puntos. Añadimos un poco de ruido para que no se
superpongan unos con otros.
geom_jitter(size=1.5,position = position_jitter(width = 0.2)) +
#4. capa con un ajuste LOESS que indica como varía stay en función de
la edad.
stat_smooth(aes(x = age, y = stay), method="loess") +
#5. Hay muchos valores bajos y algunos muy altos. Como no hay ceros,
podemos hacer una escala logarítmica en el eje y:
scale_y_log10()

El ajuste de la línea LOESS parece indicar que la longitud de la estancia no varía mucho
entre grupos de edad. Pero podria haber una interacción entre la edad y hmo. Vamos a
verlo:

ggplot(hospital, aes(age, fill=died)) +


geom_histogram(binwidth=.5, position="fill") +
facet_grid(hmo ~ ., margins=TRUE)

Parece que:

 El riesgo de morir aumenta con la edad.


 A edades bajas, la proporción de gente que falleció es mayor entre los no
asegurados que entre los asegurados. Después, la cosa parece igualarse.

Construcción del modelo

La distribución de la variable respuesta

El número de días que la gente pasa hospitalizada es un conteo (solo puede tomar
valores enteros y positivos), que además no puede tomar el valor 0. Puesto que no
queremos predecir valores negativos, optaremos por una distribución de Poisson.
Usaremos una corrección para ajustar las probabilidades teniendo en cuenta que el 0 no
puede ser predicho. En caso de que haya sobredispersión, recurriremos a una
distribución binomial negativa.

Si stayi

es el numero de días que pasa hospitalizada una persona i


, entonces, para un modelo Poisson:

 stayi∼ZTP(μi)=P(μi) / e−μi


 E(stay)=μi

 var(stay)=μi

El predictor lineal

Aquí entran en juego nuestras variables explicativas. Vamos a tener en cuenta la edad
de los pacientes, si tienen o no seguro médico y si fallecieron durante su estancia en el
hospital. Vamos a añadir interacciones entre las variables, ya que es plausible que
tengan un efecto sobre la VR.

ηi=α+β1∗agei+β2∗hmoi+β3∗died+β4∗agei∗hmoi+β5∗agei∗diedi+β6∗hmoi∗
diedi
La función de vínculo

El valor medio de stayi

se vinculará al predictor lineal mediante la función de vínculo logarítmica (log(μi)=ηi

).

Ajuste del modelo

Empezemos ajustando un glm Poisson truncado por ceros. Para usar este tipo de
modelos, vamos a cargar el paquete VGAM (que habrá que instalar):

#install.packages("VGAM") #Si no está instalado


library(VGAM)
## Loading required package: splines
## Loading required package: stats4
m1<- vglm(stay ~ age + hmo + died + age:hmo + age:died + hmo:died ,
family = pospoisson(), data = hospital)
summary(m1)
##
## Call:
## vglm(formula = stay ~ age + hmo + died + age:hmo + age:died +
## hmo:died, family = pospoisson(), data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(lambda) -3 -1.7 -0.58 0.97 21
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept) 2.4285 0.0334 72.80
## age -0.0132 0.0063 -2.10
## hmo1 -0.0542 0.0805 -0.67
## died1 -0.2119 0.0629 -3.37
## age:hmo1 -0.0147 0.0151 -0.97
## age:died1 0.0021 0.0110 0.19
## hmo1:died1 -0.0221 0.0527 -0.42
##
## Number of linear predictors: 1
##
## Name of linear predictor: log(lambda)
##
## Dispersion Parameter for pospoisson family: 1
##
## Log-likelihood: -6908 on 1486 degrees of freedom
##
## Number of iterations: 4

En este caso, summary no devuelve p-valores. En cualquier caso, para una primera
aproximación, y asumiendo que las estimas se distribuyen de acuerdo a una normal, un
z value que valga 2 o más nos puede servir para ver si una variable es o no
significativa.

Vamos a probar a eliminar la interacción age:died

m2<- vglm(stay ~ age + hmo + died + age:hmo + hmo:died , family =


pospoisson(), data = hospital)
summary(m2)
##
## Call:
## vglm(formula = stay ~ age + hmo + died + age:hmo + hmo:died,
## family = pospoisson(), data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(lambda) -3 -1.7 -0.57 0.96 21
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept) 2.425 0.0291 83.43
## age -0.013 0.0054 -2.34
## hmo1 -0.054 0.0805 -0.67
## died1 -0.201 0.0198 -10.12
## age:hmo1 -0.015 0.0151 -0.97
## hmo1:died1 -0.022 0.0527 -0.43
##
## Number of linear predictors: 1
##
## Name of linear predictor: log(lambda)
##
## Dispersion Parameter for pospoisson family: 1
##
## Log-likelihood: -6908 on 1487 degrees of freedom
##
## Number of iterations: 4

Podemos comparar m1 y m2 haciendo un LRT, o por medio de AIC:

lrtest(m1,m2)
## Likelihood ratio test
##
## Model 1: stay ~ age + hmo + died + age:hmo + age:died + hmo:died
## Model 2: stay ~ age + hmo + died + age:hmo + hmo:died
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 1486 -6908
## 2 1487 -6908 1 0.04 0.85
#¿y si usasemos AIC?:
AIC(m1)
## [1] 13830
AIC(m2)
## [1] 13828
#Parece que m2 es mejor. Quitemos ahora hmo:died:
m3<- vglm(stay ~ age + hmo + died + age:hmo , family = pospoisson(),
data = hospital)
summary(m3)
##
## Call:
## vglm(formula = stay ~ age + hmo + died + age:hmo, family =
pospoisson(),
## data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(lambda) -3 -1.7 -0.57 0.99 21
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept) 2.426 0.0291 83.5
## age -0.012 0.0054 -2.3
## hmo1 -0.056 0.0803 -0.7
## died1 -0.204 0.0184 -11.1
## age:hmo1 -0.015 0.0150 -1.0
##
## Number of linear predictors: 1
##
## Name of linear predictor: log(lambda)
##
## Dispersion Parameter for pospoisson family: 1
##
## Log-likelihood: -6908 on 1488 degrees of freedom
##
## Number of iterations: 4
lrtest(m2,m3)
## Likelihood ratio test
##
## Model 1: stay ~ age + hmo + died + age:hmo + hmo:died
## Model 2: stay ~ age + hmo + died + age:hmo
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 1487 -6908
## 2 1488 -6908 1 0.18 0.67
#ok. quitemos la interaccion age:hmo
m4<- vglm(stay ~ age + hmo + died , family = pospoisson(), data =
hospital)
summary(m4)
##
## Call:
## vglm(formula = stay ~ age + hmo + died, family = pospoisson(),
## data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(lambda) -3 -1.7 -0.59 0.98 21
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept) 2.436 0.027 89.1
## age -0.014 0.005 -2.9
## hmo1 -0.136 0.024 -5.7
## died1 -0.204 0.018 -11.1
##
## Number of linear predictors: 1
##
## Name of linear predictor: log(lambda)
##
## Dispersion Parameter for pospoisson family: 1
##
## Log-likelihood: -6909 on 1489 degrees of freedom
##
## Number of iterations: 4
lrtest(m3,m4)
## Likelihood ratio test
##
## Model 1: stay ~ age + hmo + died + age:hmo
## Model 2: stay ~ age + hmo + died
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 1488 -6908
## 2 1489 -6909 1 1.07 0.3

Todos los términos ahora parecen significativos (z values mayores que 2), asi que
podria parecer que nos podemos quedar con este modelo. Pero… (y esto en realidad es
mejor mirarlo ANTES de empezar a ajustar el modelo), todo parece indicar que hay
sobredispersión (la varianza es superior a la media). Veamos:

n <- nrow(hospital)
p <- length(coef(m4))
sum(residuals(m4, type = "pearson")^2, na.rm = TRUE)/(n - p)
## [1] 6.695

En efecto, θ

es bastante mayor que uno. Vamos a ajustar un modelo con una distribución binomial
negativa truncada por ceros (toma ya!):

m4nb<- vglm(stay ~ age + hmo + died , family = posnegbinomial(), data


= hospital)

n <- nrow(hospital)
p <- length(coef(m4nb))
sum(residuals(m4nb, type = "pearson")[,1]^2, na.rm = TRUE)/(n - p)
## [1] 1.141
#Parece que asi se arregla el problema de la sobredispersión.

summary(m4nb)
##
## Call:
## vglm(formula = stay ~ age + hmo + died, family = posnegbinomial(),
## data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(munb) -1.4 -0.71 -0.23 0.45 9.9
## log(size) -13.8 -0.29 0.46 0.76 1.1
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept):1 2.408 0.072 33.5
## (Intercept):2 0.569 0.055 10.3
## age -0.016 0.013 -1.2
## hmo1 -0.147 0.059 -2.5
## died1 -0.218 0.046 -4.7
##
## Number of linear predictors: 2
##
## Names of linear predictors: log(munb), log(size)
##
## Dispersion Parameter for posnegbinomial family: 1
##
## Log-likelihood: -4755 on 2981 degrees of freedom
##
## Number of iterations: 4

Hummm… este modelo tiene 2 interceptas. ¡Que no cunda el pánico! (Intercept):1


es la intercepta clásica, mientras que (Intercept):2 es el valor estimado para el
parámetro α

(sobredispersión) de la binomial negativa. Recuerda que en una binomial negativa:

E(Y)=μ

var(Y)=μ+α∗μ2

Es decir, que cuando α

difiere de 0 (como en el caso de nuestro modelo m4nb), la varianza es mayor que la


esperable de acuerdo a una distribución de Poisson. De hecho, si comparamos m4 con
m4nb:

AIC(m4)
## [1] 13826
AIC(m4nb)
## [1] 9521

vemos que el AIC del modelo con binomial negativa es considerablemente menor,
luego nos quedamos con él. Sin embargo, también parece que age ha dejado de ser
significativo, así que seguimos con nuestra selección:

m5nb<- vglm(stay ~ hmo + died , family = posnegbinomial(), data =


hospital)
lrtest(m4nb, m5nb)
## Likelihood ratio test
##
## Model 1: stay ~ age + hmo + died
## Model 2: stay ~ hmo + died
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 2981 -4755
## 2 2982 -4756 1 1.43 0.23
#los dos modelos no difieren, luego nos quedamos con el más sencillo.
summary(m5nb)
##
## Call:
## vglm(formula = stay ~ hmo + died, family = posnegbinomial(),
## data = hospital)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## log(munb) -1.4 -0.71 -0.22 0.44 8.7
## log(size) -16.5 -0.30 0.45 0.76 1.0
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept):1 2.33 0.028 82.9
## (Intercept):2 0.57 0.055 10.3
## hmo1 -0.15 0.059 -2.5
## died1 -0.23 0.046 -4.9
##
## Number of linear predictors: 2
##
## Names of linear predictors: log(munb), log(size)
##
## Dispersion Parameter for posnegbinomial family: 1
##
## Log-likelihood: -4756 on 2982 degrees of freedom
##
## Number of iterations: 4

Validacion del modelo

Finalmente, parece que hemos llegado a dar con nuestro modelo óptimo. Vamos a
validarlo. Como siempre, dibujamos los residuos (de Pearson) contra los valores
esperados, y contra las variables explicativas y cruzamos los dedos para no encontrar
ningún patrón:

E1 <- resid(m5nb, type = "pearson")[,1]


F1<- fitted(m5nb)

p1<-ggplot(data = NULL, aes(x=F1, y=E1)) +


stat_smooth(aes(x = F1, y = E1), method="gam") +
geom_jitter(size=0.5,position = position_jitter(width = 0.05))

#Veamos tambien si hay patrones para nuestras variables explicativas:


p2<-ggplot(data = hospital, aes(factor(age), y=E1))+
ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p3<-ggplot(data = hospital, aes(factor(hmo), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p4<-ggplot(data = hospital, aes(factor(died), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)
grid.arrange(p1,p2,p3,p4,ncol=2) ##Esta función nos permite colocar
las 4 figuras juntas

De acuerdo, no parece observarse ningún patrón claro.

Interpretación del modelo

Ahora viene la mejor parte: interpretar nuestro modelo. Recordemos que las VEs que
han “resistido” nuestro escrutinio han sido:

 hmo: con un valor de -0.146. Esto quiere decir que, independientemente de si


muere o vive (no hay interacción), un paciente con seguro pasa menos días
hospitalizado que uno sin seguro.
 died: con un valor de -0.226. Esto quiere decir que los pacientes que mueren
pasan menos días hospitalizados que los pacientes que no mueren. Un resultado
un poco macabro, pero lógico al fin y al cabo.

¿Cuantos días pasa un paciente sin seguro que no muere? Vamos a calcularlos a mano.
El caso de hmo=0 y died=0 viene representado por la intercepta del modelo
`round(coef(m5nb)[1],3). Esto quiere decir que un modelo sin truncar por ceros
predeciría $e^{2.329}=10.27días. Pero… como ya vimos, para calcular los resultados
en este tipo de modelos, tenemos que dividir la predicción que nos da el modelo entre
[1-Pr(0)], asumiendo que esta última probabilidad se distribuye de acuerdo a una
binomial negativa con los parámetros que nos da el modelo. Esta probabilidad es:

dnbinom(x=0, size=exp(0.5671208), mu=exp(2.329134))


## [1] 0.03384

…bastante baja, por lo que (en este caso) el resultado obtenido por el modelo truncado
por ceros no va a diferir mucho del que nos daría una binomial negativa “de las
normalitas”:

# El número de días de hospitalización que nuestro modelo predice para


un paciente sin seguro y que no muere es...
exp(2.329134)/ (1- dnbinom(x=0, size=exp(0.5671208),
mu=exp(2.329134)))
# ... redoble de tambores :)

¡10.63 días!

Prueba tú mismo #1:

Calcula el número de días que predice nuestro modelo para las combinaciones de las
VEs que quedan.
Un poco lento, aunque no viene mal calcular estas cosas para comprender lo que se está
haciendo. Por supuesto, como siempre, la función predict nos puede hacer la vida más
fácil:

hospital$pred<-predict(m5nb,type="response")
head(hospital)
## stay age hmo died pred
## 1 4 4 0 0 10.629
## 2 9 4 1 0 9.265
## 3 3 7 1 1 7.516
## 4 9 6 0 0 10.629
## 5 1 7 0 1 8.596
## 6 4 5 0 1 8.596

Modelos inflados por ceros

En ecología no es muy habitual encontrar conteos en los que no pueda aparecer el valor
0. Sin embargo, sí que es mucho más usual encontrar datos de conteos en los que hay un
numero de ceros mayor que el que cabría esperar de acuerdo a una distribución de
Poisson o una binomial negativa.

Esto puede causar problemas en nuestros modelos ya que, de no tener en cuenta el


exceso de ceros:

 Las estimas de los coeficientes pueden ser poco fiables.


 Puede haber sobredispersión.

Hay varios motivos que pueden llevar a que en un conteo aparezcan ceros. Por ejemplo,
en el contexto de la abundancia de pájaros en un área forestal:

1. Hay errores estructurales. Es decir, que una especie no está presente en un


parche porque el hábitat no es el adecuado.
2. Hay errores de diseño, debidos a un pobre diseño experimental o muestral. Por
ejemplo, si buscamos a una especie en una época en la los individuos se
encuentran en otro sitio (e.g. golondrinas en invierno), es muy probable que
nuestros conteos contengan una gran proporcion de ceros. Otro error de este tipo
es muestrear durante demasiado poco tiempo, o a una escala espacial
inadecuada.
3. Hay errores de observador. Esto ocurre cuando dos especies son similares y el
observador no sabe distinguirlas, o cuando son dificiles de detectar.
4. Por último el error de los propios pájaros. Es decir, que el hábitat es el
adecuado, pero el pájaro no está presente.

De entre estas posible fuentes de ceros, los de diseño, los debidos al observador y los de
los pájaros (números 2, 3 y 4 de la lista anterior) se consideran falsos ceros, mientras
que los estructurales se consideran ceros auténticos. La presencia de falsos ceros puede
llevar a que haya una sobreabundancia de ceros en nuestros datos. En esta sección
vamos a ver técnicas (modelos inflados por ceros y modelos alterados por ceros) que
permiten tener en cuenta este problema.
Vamos a explorar una base de datos para ilustrar esto. En ella aparecen el numero de
peces count que ha pescado una serie de grupos de pescadores en un parque, así como
una serie de características de los grupos:

fish<-read.table(paste(raiz,"Datos/pesca.txt", sep=""), header=T)


str(fish)
## 'data.frame': 250 obs. of 8 variables:
## $ nofish : int 1 0 0 0 0 0 0 0 1 0 ...
## $ livebait: int 0 1 1 1 1 1 1 1 0 1 ...
## $ camper : int 0 1 0 1 0 1 0 0 1 1 ...
## $ persons : int 1 1 1 2 1 4 3 4 3 1 ...
## $ child : int 0 0 0 1 0 2 1 3 2 0 ...
## $ xb : num -0.896 -0.558 -0.402 -0.956 0.437 ...
## $ zg : num 3.05 1.746 0.28 -0.602 0.528 ...
## $ count : int 0 0 0 0 1 0 0 0 0 1 ...
plot(table(fish$count))

Se observa que, efectivamente, una gran parte de los grupos no pescan nada. En
realidad, si los datos siguieran una distribución de Poisson, el número de ceros que
cabría esperar es mucho menor que el observado en estos datos.

Modelos inflados y alterados

Ahora vamos a hablar de ZIP y ZAP (y de ZINB y ZANB). !No confundir con estos!

Hay básicamente dos estrategias para lidiar con el problema de los ceros:

1. Asumir que todos los ceros son iguales (sin distinguir entre falsos y auténticos).
Este tipo de modelos constan de dos partes: en una primera parte se consideran
todos los datos como ceros o no-ceros y se modela la probabilidad de que una
observación sea cero (en función de las variables explicativas seleccionadas)
usando un modelo binomial. Posteriormente, las observaciones que no son cero
se modelizan usando modelos truncados por ceros, como los que acabamos de
ver. Afortunadamente hay funciones de R que realizan simultáneamente ambos
procesos. Estos modelos se llaman Modelos en dos partes o modelos ZAP o
ZANB; ZA es por Zero Altered, P indica el uso de la distribución de Poisson y
NB el de la binomial negativa.
2. Asumir que los ceros proceden de dos procesos distintos: el proceso binomial y
el proceso de Poisson. Igual que en los ZAP, se hace un glm binomial para
modelizar la probabilidad de medir un 0 (los falsos ceros; por ejemplo cuando el
observador no ha visto a ningún individuo de la especie en cuestión a pesar de
que está presente). Posteriormente se modeliza la probabilidad de obtener el
resto de valores, incluyendo ceros (los ceros auténticos; por ejemplo cuando el
hábitat no es adecuado para la especie en cuestión). Estos modelos se llaman
Modelos mezclados (mixture models) o modelos ZIP (Zero Inflated) o ZINB.

Ambos tipos de modelos nos permiten abordar el exceso de ceros. La elección de uno u
otro modelo debería basarse en conocimiento a priori de las fuentes de ceros en nuestro
problema. En principio, si consideramos que por algún motivo hay una gran cantidad de
falsos ceros en nuestros datos, deberíamos decantarnos por modelos ZI(P/NB), que nos
van a permitir descubrir los motivos que llevan a medir falsos ceros (y tal vez tomar
medidas para evitarlos en futuros trabajos). Si por el contrario pensamos que la mayoría
de los ceros son auténticos aunque haya muchos (e.g. cuando una especie es muy
selectiva en cuanto a las condiciones ambientales en las que aparece, pero somos
capaces de detectarla sin muchos problemas), podemos optar por los ZA(P/NB).

Ok, empecemos por los ZA(P/NB).

Como acabamos de ver, los ZAP (o hurdle models) son conceptualmente muy sencillos:
primero realizamos una regresión binomial para estimar la probabilidad de que una
observación sea cero; después, usamos un modelo truncado por ceros para analizar los
datos que no son cero.

Vamos a seguir con el ejemplo de los pescadores. Supongamos que los gestores del
parque quieren vigilar especialmente a los grupos de gente que pescan muchos más
peces de la cuenta. En cuanto a la gente que no pesca nada, les da igual si es porque
sean pésimos pescadores o porque en realidad no hayan ido a pescar; el objetivo es
conocer las características de los grupos que pescan mucho. En resumen, queremos
conocer los factores que determinan el número de peces pescados por los grupos,
teniendo en cuenta que hay muchos grupos que no pescan ningún pez.

Como siempre, lo primero es echarle un ojo a las variables:

str(fish)
## 'data.frame': 250 obs. of 8 variables:
## $ nofish : int 1 0 0 0 0 0 0 0 1 0 ...
## $ livebait: int 0 1 1 1 1 1 1 1 0 1 ...
## $ camper : int 0 1 0 1 0 1 0 0 1 1 ...
## $ persons : int 1 1 1 2 1 4 3 4 3 1 ...
## $ child : int 0 0 0 1 0 2 1 3 2 0 ...
## $ xb : num -0.896 -0.558 -0.402 -0.956 0.437 ...
## $ zg : num 3.05 1.746 0.28 -0.602 0.528 ...
## $ count : int 0 0 0 0 1 0 0 0 0 1 ...
head(fish)
## nofish livebait camper persons child xb zg count
## 1 1 0 0 1 0 -0.8963 3.0504 0
## 2 0 1 1 1 0 -0.5583 1.7461 0
## 3 0 1 0 1 0 -0.4017 0.2799 0
## 4 0 1 1 2 1 -0.9563 -0.6015 0
## 5 0 1 0 1 0 0.4369 0.5277 1
## 6 0 1 1 4 2 1.3945 -0.7075 0
tail(fish)
## nofish livebait camper persons child xb zg count
## 245 0 1 0 3 0 -0.2911 1.3155 0
## 246 1 1 1 2 0 -0.7552 2.3242 0
## 247 0 1 1 4 3 1.7949 -5.6259 0
## 248 0 1 1 2 1 -0.3926 0.6773 0
## 249 1 1 1 3 2 1.3746 -2.5956 0
## 250 1 1 1 2 1 0.8288 -1.4571 0

Hay 250 observaciones de grupos que acudieron al parque. De cada grupo se sabe el
número de peces que pescaron (count), el número de niños que forman parte del grupo
(child), el número de miembros del grupo (persons) y si llevaban o no una caravana
(camper).

Nos encontramos con un posible problema: persons es el número total de personas,


incluyendo niños, de cada grupo. Un grupo con muchos niños tendrá forzosamente
muchas personas, mientras que un grupo con pocas personas no puede tener mucho
niños, por lo que es posible que persons y child estén correlacionados:

cor(fish$persons,fish$child, method="spearman")
## [1] 0.5412

Podemos solucionar esto simplemente creando una nueva variable que indique el
número de adultos:

fish$adultos<- fish$persons - fish$child #los adultos son el total de


personas menos los niños
cor(fish$adultos,fish$child, method="spearman") #Bien! Se ha reducido
bastante la correlación
## [1] -0.1957

Ahora veamos como varía el número de peces pescados en función de nuestras VEs:

library(lattice)
histogram(~count | adultos, data = fish, type = "count")

#... parece que nadie pesca solo


histogram(~count | child, data = fish, type = "count")

#... parece que si se va con niños no se va a pescar, o no se pesca


casi nada
histogram(~count | camper, data = fish, type = "count")

#... parece que quienes llevan caravana pescan más que quienes no

Ok. Pues vamos a hacer nuestro modelo. Como estamos analizando dos procesos,
usaremos dos conjuntos de variables explicativas (unas para la parte binomial y otras
para la truncada por ceros). Lo primero que vamos a hacer es crear la fórmula con las
variables explicativas que vamos a incluir en nuestro modelo. Como es un modelo que
incluye la mezcla de dos procesos (poisson y binomial), tenemos que indicar:

1. Nuestra variable respuesta (`count ~’).


2. Las variables explicativas para el proceso de poisson.
3. Las variables explicativas para el proceso binomial.

Esto se hace asi:


f1<-formula(count ~ adultos + child + camper + adultos:child +
adultos:camper + camper:child |
adultos + child + camper + adultos:child + adultos:camper
+ camper:child)

El símbolo | separa las variables explicativas del proceso binomial (a la derecha) de las
del proceso de poisson (a la izquierda). Podríamos escribir todo dentro de la función de
R que ajusta este tipo de modelos (hurdle), pero es más cómodo (y menos lioso)
escribir la fórmula aparte. Carguemos el paquete correspondiente (pscl) y ajustemos el
modelo:

library(pscl)
## Loading required package: MASS
## Classes and Methods for R developed in the
##
## Political Science Computational Laboratory
##
## Department of Political Science
##
## Stanford University
##
## Simon Jackman
##
## hurdle and zeroinfl functions by Achim Zeileis
Zap1 <- hurdle(f1, dist = "poisson",link = "logit", data = fish)
summary(Zap1)
##
## Call:
## hurdle(formula = f1, data = fish, dist = "poisson", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -3.9008 -0.6511 -0.4518 0.0511 17.5950
##
## Count model coefficients (truncated poisson with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.0726 0.3110 -0.23 0.81541
## adultos 0.5484 0.0936 5.86 4.6e-09 ***
## child 1.2504 0.3489 3.58 0.00034 ***
## camper -0.4174 0.3555 -1.17 0.24028
## adultos:child -0.3214 0.1173 -2.74 0.00614 **
## adultos:camper 0.4121 0.1045 3.94 8.0e-05 ***
## child:camper -0.8718 0.2348 -3.71 0.00021 ***
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.7718 0.6439 -2.75 0.0059 **
## adultos 0.9384 0.3087 3.04 0.0024 **
## child -1.2066 0.8072 -1.49 0.1350
## camper -0.0735 0.7922 -0.09 0.9261
## adultos:child -0.1379 0.3503 -0.39 0.6938
## adultos:camper 0.4432 0.4013 1.10 0.2694
## child:camper 0.6179 0.5447 1.13 0.2567
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of iterations in BFGS optimization: 16
## Log-likelihood: -723 on 14 Df
En effecto, summary tiene dos partes: una primera parte para el modelo truncado por
ceros (truncated poisson with log link) y una segunda parte para el modelo
binomial (binomial with logit link).

Una vez hecho esto, vamos a proceder a seleccionar las VEs que nos vamos a quedar.
Este proceso puede ser un poco largo, al estar compuesto el modelo de dos partes
diferentes. Para hacerlo, vamos a ir eliminando de cada una de las partes la interacción
con un p-valor más alto. En este caso esa variable es adultos:child, tanto en la parte
binomial como en la poisson:

¡Recuerda! aunque una variable no sea significativa por sí sola, no debemos eliminarla
del modelo si forma parte de una interacción significativa.

#quitamos adultos:child de poisson:


f1A<- formula(count ~ adultos + child + camper + adultos:camper +
camper:child |
adultos + child + camper + adultos:child + adultos:camper
+ camper:child)
#quitamos adultos:child de binomial:
f1B<- f1<-formula(count ~ adultos + child + camper + adultos:child +
adultos:camper + camper:child |
adultos + child + camper + adultos:camper + camper:child)

Zap1A<- hurdle(f1A, dist = "poisson",link = "logit", data = fish)

Zap1B<- hurdle(f1B, dist = "poisson",link = "logit", data = fish)

#Comparamos los modelos simplificados con el original:

library(lmtest)
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
##
## Attaching package: 'lmtest'
##
## The following object is masked from 'package:VGAM':
##
## lrtest
lrtest(Zap1, Zap1A) ##Esta función lrtest es la de lmtest, no la del
paquete VGAM, que aqui no sirve
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + adultos:child + adultos:camper +
## camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 14 -723
## 2 13 -726 -1 6.83 0.009 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
lrtest(Zap1, Zap1B)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:camper +
## camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 14 -723
## 2 13 -723 -1 0.15 0.69
AIC(Zap1, Zap1A, Zap1B)
## df AIC
## Zap1 14 1473
## Zap1A 13 1478
## Zap1B 13 1471

El modelo sin adultos:child en la parte binomial (Zap1B) es mejor (no difiere de


Zap1 de acuerdo al LRT y tiene un AIC menor. En cambio, quitar adultos:child de la
parte Poisson empeora nuestro modelo bastante (como ya cabía esperar de acuerdo al p-
valor de summary). Por lo tanto, eliminamos adultos:child de la parte binomial y
seguimos refinando el modelo:

summary(Zap1B)
##
## Call:
## hurdle(formula = f1B, data = fish, dist = "poisson", link =
"logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -3.7437 -0.6593 -0.4503 0.0325 16.9913
##
## Count model coefficients (truncated poisson with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.0726 0.3110 -0.23 0.81541
## adultos 0.5484 0.0936 5.86 4.6e-09 ***
## child 1.2504 0.3489 3.58 0.00034 ***
## camper -0.4174 0.3555 -1.17 0.24028
## adultos:child -0.3214 0.1173 -2.74 0.00614 **
## adultos:camper 0.4121 0.1045 3.94 8.0e-05 ***
## child:camper -0.8718 0.2348 -3.71 0.00021 ***
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.6988 0.6127 -2.77 0.00556 **
## adultos 0.8963 0.2862 3.13 0.00174 **
## child -1.4781 0.4390 -3.37 0.00076 ***
## camper -0.0475 0.7864 -0.06 0.95182
## adultos:camper 0.4150 0.3909 1.06 0.28839
## child:camper 0.6909 0.5207 1.33 0.18458
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of iterations in BFGS optimization: 16
## Log-likelihood: -723 on 13 Df
#Vamos a quitar adultos:camper de la parte binomial:

f1C<- formula(count ~ adultos + child + camper + adultos:child +


adultos:camper + camper:child |
adultos + child + camper + camper:child)
Zap1C<- hurdle(f1C, dist = "poisson",link = "logit", data = fish)

lrtest(Zap1B, Zap1C)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:camper +
## camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 13 -723
## 2 12 -723 -1 1.12 0.29
AIC(Zap1B, Zap1C)
## df AIC
## Zap1B 13 1471
## Zap1C 12 1471
#Todo parece indicar que es seguro eliminar esa interacción.
summary(Zap1C)
##
## Call:
## hurdle(formula = f1C, data = fish, dist = "poisson", link =
"logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -3.3486 -0.6905 -0.4427 0.0864 15.4957
##
## Count model coefficients (truncated poisson with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.0726 0.3110 -0.23 0.81541
## adultos 0.5484 0.0936 5.86 4.6e-09 ***
## child 1.2504 0.3489 3.58 0.00034 ***
## camper -0.4174 0.3555 -1.17 0.24028
## adultos:child -0.3214 0.1173 -2.74 0.00614 **
## adultos:camper 0.4121 0.1045 3.94 8.0e-05 ***
## child:camper -0.8718 0.2348 -3.71 0.00021 ***
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.143 0.470 -4.56 5.1e-06 ***
## adultos 1.135 0.194 5.86 4.7e-09 ***
## child -1.546 0.457 -3.38 0.00072 ***
## camper 0.681 0.396 1.72 0.08590 .
## child:camper 0.757 0.533 1.42 0.15539
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of iterations in BFGS optimization: 16
## Log-likelihood: -723 on 12 Df
#Seguimos quitando la interacción que queda (camper:child):
f1D<- formula(count ~ adultos + child + camper + adultos:child +
adultos:camper + camper:child |
adultos + child + camper )
Zap1D<- hurdle(f1D, dist = "poisson",link = "logit", data = fish)

lrtest(Zap1C, Zap1D)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 12 -723
## 2 11 -724 -1 2.18 0.14
AIC(Zap1C, Zap1D)
## df AIC
## Zap1C 12 1471
## Zap1D 11 1471

De acuerdo al LRT, el modelo sin camper:child en la parte binomial no difiere del que
sí la incluye; El AIC de ambos es muy similar. Vamos a quedarnos con el modelo que
no incluye esa interacción:

summary(Zap1D)
##
## Call:
## hurdle(formula = f1D, data = fish, dist = "poisson", link =
"logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -3.4206 -0.7351 -0.4477 0.0481 15.7656
##
## Count model coefficients (truncated poisson with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.0726 0.3110 -0.23 0.81541
## adultos 0.5484 0.0936 5.86 4.6e-09 ***
## child 1.2504 0.3489 3.58 0.00034 ***
## camper -0.4174 0.3555 -1.17 0.24028
## adultos:child -0.3214 0.1173 -2.74 0.00614 **
## adultos:camper 0.4121 0.1045 3.94 8.0e-05 ***
## child:camper -0.8718 0.2348 -3.71 0.00021 ***
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.309 0.461 -5.01 5.6e-07 ***
## adultos 1.110 0.191 5.81 6.2e-09 ***
## child -1.028 0.234 -4.40 1.1e-05 ***
## camper 1.018 0.325 3.14 0.0017 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of iterations in BFGS optimization: 16
## Log-likelihood: -724 on 11 Df

Llegados a este punto, todas las variables que quedan en el modelo son significativas,
por lo que podemos dar por concluida la seleccion de variables.
Para finalizar, solo quedaría validar el modelo. De nuevo, miramos los residuos (de
Pearson) y los comparamos con los valores ajustados y con cada una de las variables
explicativas (y cruzamos los dedos esperando no encontrar ningún patrón…)

E1<- residuals(Zap1D, type="pearson")


F1<- predict(Zap1D, type="response")

p1<-ggplot(data = NULL, aes(x=F1, y=E1)) +


stat_smooth(aes(x = F1, y = E1), method="gam") +
ylab("Pearson residuals") +
xlab("Fitted values") +
geom_jitter(size=1,position = position_jitter(width = 0.05))

#Veamos tambien si hay patrones para nuestras variables explicativas:


p2<-ggplot(data = fish, aes(factor(adultos), y=E1))+
ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p3<-ggplot(data = fish, aes(factor(child), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p4<-ggplot(data = fish, aes(factor(camper), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

grid.arrange(p1,p2,p3,p4,ncol=2)

Bueno… no se ven patrones muy claros. Sin embargo no hemos comprobado si hay
sobredispersión en la parte poisson de nuestro modelo. ¿Como se hace? Ajustando un
modelo con una distribución binomial negativa (ZANB), que permite que la varianza
aumente más rápido que la media y comparándolo con nuestro modelo ZAP.

¡Atención! El haber ajustado primero el modelo ZAP se debe a motivos puramente


pedagógicos. Cuando analices tus propios datos es conveniente seleccionar el tipo de
modelo antes de pasar a las etapas de selección de variables y validación. La existencia
de algunos valores de count muy elevados es un indicador de que puede haber
sobredispersión en los datos.

ZANB

La mejor forma de ver si elegimos el modelo ZAP o el ZANB es ajustar ambos modelos
(saturados) y compararlos:

f1<-formula(count ~ adultos + child + camper + adultos:child +


adultos:camper + camper:child |
adultos + child + camper + adultos:child + adultos:camper
+ camper:child)
#Modelo poisson:
Zap1<- hurdle(f1, dist = "poisson",link = "logit", data = fish)
#Modelo binomial negativa:
Zanb1<- hurdle(f1, dist = "negbin",link = "logit", data = fish)

lrtest(Zap1, Zanb1) #Recuerda que un modelo poisson y un NB pueden


compararse por medio de LRT!
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 14 -723
## 2 15 -390 1 665 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
AIC(Zap1, Zanb1)
## df AIC
## Zap1 14 1473.3
## Zanb1 15 810.7

En efecto, todo indica que Zanb1 es mucho mejor. De nuevo, vamos a seleccionar las
variables explicativas.

Prueba tú mismo #2:

 Partiendo de Zanb1, selecciona las variables explicativas, eliminando la menos


significativa en cada paso.
 Valida tú modelo. ¿Hay algún patrón en los residuos?
 Interpreta tu modelo. ¿que variables influyen en que se cojan o no peces? ¿y en
el número de peces pescados?

Llega el turno de los ZIP(NB).

Como ya dijimos antes, la principal diferencia entre los ZAP y los ZIP es que en estos
últimos estamos interesados en distinguir los distintos orígenes de los ceros observados,
es decir, consideramos que hay ceros auténticos y ceros falsos. Vamos a utilizar una
nueva base de datos para ver estos modelos (datos de Hemmingsen et al. 2005):

ParasiteCod<-read.table(paste(raiz,"Datos/ParasiteCod.txt", sep=""),
header=T)
str(ParasiteCod)
## 'data.frame': 1254 obs. of 11 variables:
## $ Sample : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Intensity : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Prevalence: int 0 0 0 0 0 0 0 0 0 0 ...
## $ Year : int 1999 1999 1999 1999 1999 1999 1999 1999 1999
1999 ...
## $ Depth : int 220 220 220 220 220 220 220 194 194 194 ...
## $ Weight : int 148 144 146 138 40 68 52 3848 2576 1972 ...
## $ Length : int 26 26 27 26 17 20 19 77 67 60 ...
## $ Sex : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Stage : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Age : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Area : int 2 2 2 2 2 2 2 3 3 3 ...
head(ParasiteCod)
## Sample Intensity Prevalence Year Depth Weight Length Sex Stage
Age Area
## 1 1 0 0 1999 220 148 26 0 0
0 2
## 2 2 0 0 1999 220 144 26 0 0
0 2
## 3 3 0 0 1999 220 146 27 0 0
0 2
## 4 4 0 0 1999 220 138 26 0 0
0 2
## 5 5 0 0 1999 220 40 17 0 0
0 2
## 6 6 0 0 1999 220 68 20 0 0
0 2
tail(ParasiteCod)
## Sample Intensity Prevalence Year Depth Weight Length Sex Stage
Age
## 1249 1249 89 1 2001 260 1414 56 1 1
6
## 1250 1250 90 1 2001 228 224 31 1 1
2
## 1251 1251 104 1 2001 140 690 43 2 1
3
## 1252 1252 125 1 2001 140 754 44 2 1
3
## 1253 1253 128 1 2001 140 1270 55 2 4
7
## 1254 1254 257 1 2001 228 370 35 2 1
3
## Area
## 1249 2
## 1250 4
## 1251 4
## 1252 4
## 1253 4
## 1254 4

La columna Intensity recoge el número de individuos de un determinado parásito


encontrados en ejemplares de bacalao capturados en distintos años y areas de la costa de
Noruega. Además tenemos información acerca de ciertas características de cada
bacalao. Vamos a tratar de analizar el número de parásitos en función del año (Year), la
zona de estudio (Area) y la longitud del bacalao (Length)

Antes de nada, vamos a decirle a R que tanto Area como Year son factores, y no
variables cuantitativas.

ParasiteCod$fArea <- factor(ParasiteCod$Area)


ParasiteCod$fYear <- factor(ParasiteCod$Year)

Después, para facilitar las cosas más adelante, vamos a eliminar las filas en las que no
disponemos de datos para alguna de las variables que utilizamos:
I1 <- is.na(ParasiteCod$Intensity) |
is.na(ParasiteCod$fArea) |
is.na(ParasiteCod$fYear) |
is.na(ParasiteCod$Length)
ParasiteCod2 <- ParasiteCod[!I1, ]

Observemos ahora la distribución del número de parásitos en nuestros bacalaos:

plot(table(ParasiteCod2$Intensity))

Gran parte de los bacalaos no tienen ningún parásito (Como cabía esperar de una base
de datos para explicar los modelos inflados por ceros), mientras que bastantes tienen
unos pocos y unos pocos bacalaos tienen muchísimos parásitos. Pero ¿de dónde vienen
los ceros?

1. Algunos bacalaos no han estado expuestos al parásito, bien porque en su región


no está presente el vector que propaga los parásitos (una especie de cangrejo), o
bien porque han llegado recientemente desde una zona libre de parásitos. Estos
se consideran falsos ceros.
2. Algunos ceros pueden deberse a errores cometidos por el observador, que no
encuentra parásitos en un bacalao que sí los tiene (algo que parece ser fácil que
ocurra cuando el bacalao no está muy infectado). Estos también son falsos ceros.
3. El resto de ceros vienen de peces que han estado expuestos al vector, pero que
por algún motivo (habitat, inmunidad, condiciones ambientales) no han sido
infectados. Estos son ceros auténticos.

En este caso, nos interesa distinguir unos ceros de otros para 1) intentar tomar medidas
para reducir el número de falsos ceros (por ejemplo, formar a la persona que muestrea
los parásitos o evitar las áreas en las que no está el vector) y 2) conocer las
características de los bacalaos que, habiendo estado expuestos, no sufren infecciones.

Entonces, ¿cual es la probabilidad de observar un 0?

Supongamos que Pr(Yi)

es la probabilidad de que un bacalao i tenga Yi parásitos. La probabilidad de


que Yi

sea 0 es en realidad la suma de los falsos ceros, más la probabilidad de que,


una vez eliminadas las observaciones que no son falsos ceros, se produzca un
cero auténtico:

Pr(Yi=0) = Pr(falsos ceros) + (1−Pr(falsos ceros)) x Pr(ceros auténticos)

Esto es, dividimos los datos en dos grupos: el primero contiene sólo ceros (los
falsos ceros), y el segundo contiene tanto ceros como otros números (mayores
que cero). Sin embargo, estos grupos son imaginarios; no sabemos qué ceros
pertenecen a cada uno de los grupos (aunque sí sabemos que las que no son
cero pertenecen al segundo grupo).

Es fácil ver que el primer grupo se puede estudiar usando una distribución
binomial, donde π

es la probabilidad de observar un falso cero. Es decir:

Pr(Yi=0) = πi+(1−πi) x Pr(ceros auténticos)

mientras que para el segundo grupo se puede usar una distribución para
conteos que permita la obtención de ceros: Poisson (o binomial negativa en
caso de sobredispersión). En el caso de Poisson, como ya hemos visto, la
probabilidad de observar un cero es:

Pr(0;μi)=μ0 e−μi0! = e−μi


;

Con lo que finalmente obtenemos que la probabilidad de observar un 0 (del tipo


que sea) es:

Pr(Yi=0) = πi+(1−πi) x e−μi


Además, siguiendo un procedimient análogo se llega facilmente a estimar la
probabilidad de observar un valor mayor que cero (la probabilidad de que un
pez tenga parásitos y que además haya quedado registrado correctamente):

Pr(Yi>0) = (1−πi) x μyie−μiyi!


Y una vez aqui, ¿qué? Con estas dos fórmulas podemos contruir la función de
probabilidad en la que se basan los modelos ZIP.

¿Sabrías calcular la probabilidad de observar 0 parásitos si πi=0.3

y μi=5

? ¿y 4 parásitos?

En realidad es fácil ver que lo único que tendremos que modelizar son los
valores de πi

(binomial) y de μi
(Poisson) en función de las covariables que elijamos:

πi=eηbin1+eηbin
, donde ηbin es la función vínculo de la parte binomial del modelo
(αbin+β1binx1bin+...+βnbinxnbin

μi=eηpoi
, donde ηpoi es la función vínculo de la parte poisson del modelo
(αpoi+β1poix1poi+...+βnpoixnpoi

Afortunadamente, hay funciones de que utilizan procedimientos de máxima


verosimilitud para los coeficientes βbin

y βpoi

, así como sus errores estándar.

Manos a la obra. Bacalaos usando ZIP y ZINB.

En este caso, nos interesa predecir tanto el número de parásitos en los bacalaos que han
podido ser infectados como la probabilidad de que un bacalao no tenga parásitos por no
haber estado expuesto. La distinción fundamental con respecto a los modelos ZA es que
queremos distinguir entre los falsos ceros y los ceros auténticos.

Para ajustar estos modelos vamos a usar de nuevo el paquete pscl; en este caso, la
función zeroinfl. Construimos un modelo saturado que incluye el año, el área, la
interacción año:area y la longitud del bacalao.

Prueba tú mismo #3:

Representa gráficamente la distribución del número de parásitos en función de las


variables explicativas seleccionadas (fYear, fArea y Length) ¿cómo interpretas estas
figuras?

Construimos un modelo ZIP saturado, y en paralelo, un modelo ZINB, y elegimos el


que mejor se ajusta a nuestros datos:
f1<-formula(Intensity ~ fArea * fYear + Length | fArea*fYear + Length)

Zip1 <- zeroinfl(f1, dist = "poisson",link = "logit", data =


ParasiteCod2)
Zinb1 <- zeroinfl(f1, dist = "negbin",link = "logit", data =
ParasiteCod2)

lrtest(Zip1,Zinb1)
## Likelihood ratio test
##
## Model 1: Intensity ~ fArea * fYear + Length | fArea * fYear +
Length
## Model 2: Intensity ~ fArea * fYear + Length | fArea * fYear +
Length
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 26 -6818
## 2 27 -2450 1 8734 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
AIC(Zip1,Zinb1)
## df AIC
## Zip1 26 13687
## Zinb1 27 4955

El modelo ZINB es claramente superior al ZIP. A partir de ahora trabajaremos sobre él.
Vamos a seleccionar las variables explicativas de forma similar a lo que hicimos en los
modelos ZA:

summary(Zinb1)
##
## Call:
## zeroinfl(formula = f1, data = ParasiteCod2, dist = "negbin", link =
"logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.614 -0.443 -0.358 -0.125 11.453
##
## Count model coefficients (negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 3.73390 0.34440 10.84 <2e-16 ***
## fArea2 0.19777 0.32913 0.60 0.548
## fArea3 -0.64673 0.27779 -2.33 0.020 *
## fArea4 0.70750 0.25226 2.80 0.005 **
## fYear2000 0.06389 0.29564 0.22 0.829
## fYear2001 -0.93915 0.60606 -1.55 0.121
## Length -0.03641 0.00511 -7.13 1e-12 ***
## fArea2:fYear2000 -0.65399 0.53542 -1.22 0.222
## fArea3:fYear2000 1.02496 0.42960 2.39 0.017 *
## fArea4:fYear2000 0.53453 0.41497 1.29 0.198
## fArea2:fYear2001 0.96727 0.71817 1.35 0.178
## fArea3:fYear2001 1.00270 0.67750 1.48 0.139
## fArea4:fYear2001 0.85516 0.65440 1.31 0.191
## Log(theta) -0.96662 0.09634 -10.03 <2e-16 ***
##
## Zero-inflation model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.1909 0.7813 0.24 0.80697
## fArea2 2.0137 0.5729 3.51 0.00044 ***
## fArea3 1.9053 0.5499 3.46 0.00053 ***
## fArea4 -0.7362 0.8622 -0.85 0.39321
## fYear2000 -1.0717 2.0002 -0.54 0.59209
## fYear2001 3.2932 0.7104 4.64 3.6e-06 ***
## Length -0.0388 0.0120 -3.23 0.00125 **
## fArea2:fYear2000 0.4654 2.0789 0.22 0.82286
## fArea3:fYear2000 -0.7945 2.1576 -0.37 0.71269
## fArea4:fYear2000 -13.5700 1509.5741 -0.01 0.99283
## fArea2:fYear2001 -3.2074 0.8360 -3.84 0.00012 ***
## fArea3:fYear2001 -3.5041 0.8300 -4.22 2.4e-05 ***
## fArea4:fYear2001 -2.9105 1.1046 -2.63 0.00841 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta = 0.38
## Number of iterations in BFGS optimization: 53
## Log-likelihood: -2.45e+03 on 27 Df

Puesto que Length es significativa en ambas partes del modelo, el paso evidente es
probar a eliminar la interacción Area:Year:

#Elimino Area:Year de la parte del conteo


f1A<-formula(Intensity ~ fArea+fYear + Length | fArea*fYear + Length)
#Elimino Area:Year de la parte binomial
f1B<-formula(Intensity ~ fArea*fYear + Length | fArea+fYear + Length)

Zinb1A <- zeroinfl(f1A, dist = "negbin",link = "logit", data =


ParasiteCod2)
Zinb1B <- zeroinfl(f1B, dist = "negbin",link = "logit", data =
ParasiteCod2)

lrtest(Zinb1, Zinb1A)
## Likelihood ratio test
##
## Model 1: Intensity ~ fArea * fYear + Length | fArea * fYear +
Length
## Model 2: Intensity ~ fArea + fYear + Length | fArea * fYear +
Length
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 27 -2450
## 2 21 -2458 -6 14.2 0.027 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
lrtest(Zinb1, Zinb1B)
## Likelihood ratio test
##
## Model 1: Intensity ~ fArea * fYear + Length | fArea * fYear +
Length
## Model 2: Intensity ~ fArea * fYear + Length | fArea + fYear +
Length
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 27 -2450
## 2 21 -2460 -6 18.9 0.0044 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
AIC(Zinb1, Zinb1A, Zinb1B)
## df AIC
## Zinb1 27 4955
## Zinb1A 21 4957
## Zinb1B 21 4962
Parece que no podemos (debemos) eliminar ningún término (aunque los test son
aproximados y una p=0.027 podria no convencernos del todo). El hecho de tener
variables explicativas categóricas añade cierta dificultad a la hora de incluir nuestros
resultados en una posible publicación o informe (e.g. hay 6 p-valores asociados a la
interacción Area:Year en la parte binomial). Para solventar esto, podemos comparar el
modelo seleccionado (Zinb1) con un modelo en el que eliminemos el término en
cuestión. Por ejemplo:

#Elimino Area:Year de la parte binomial


f2B<-formula(Intensity ~ fArea*fYear + Length | fArea+fYear + Length)
Zinb2B <- zeroinfl(f2B, dist = "negbin",link = "logit", data =
ParasiteCod2)
lrtest(Zinb1, Zinb2B)
## Likelihood ratio test
##
## Model 1: Intensity ~ fArea * fYear + Length | fArea * fYear +
Length
## Model 2: Intensity ~ fArea * fYear + Length | fArea + fYear +
Length
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 27 -2450
## 2 21 -2460 -6 18.9 0.0044 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

En una posible publicación podemos mostrar el valor del estadístico Chi cuadrado, los
gdl y el p-valor (χ2

=18.85.29; df=6; p=0.004), repitiendo este proceso para todas las variables explicativas.

Inciso: ¿Es necesario usar el modelo inflado por ceros?

Nada de lo que hemos visto hasta ahora nos indica que nuestro modelo inflado por ceros
sea mejor que una binomial negativa normal y corriente. El problema aquí es que es
dificil comparar modelos que no están anidados. Sin embargo, el test de Vuong,
disponible en la función pscl::vuong, nos permite hacer estas comparaciones.
Probemos a calcular el modelo binomial negativa (usando la función glm.nb de MASS):

library(MASS)

nb1A<-glm.nb(Intensity ~ fArea+fYear + Length, data = ParasiteCod2)

vuong(Zinb1, nb1A)
## Vuong Non-Nested Hypothesis Test-Statistic: -61.27
## (test-statistic is asymptotically distributed N(0,1) under the
## null that the models are indistinguishible)
## in this case:
## model2 > model1, with p-value <2e-16

Perfecto; el test nos indica que el modelo inflado por ceros es mucho mejor que su
equivalente sin inflar.

Últimos pasos: validación e interpretación


Ya solo nos queda validar el modelo. Como siempre, calculamos los residuos de
Pearson y los representamos contra todo:

E1<- residuals(Zinb1, type="pearson")


F1<- predict(Zinb1, type="response")

p1<-ggplot(data = NULL, aes(x=F1, y=E1)) +


stat_smooth(aes(x = F1, y = E1), method="gam") +
ylab("Pearson residuals") +
xlab("Fitted values") +
geom_jitter(size=1,position = position_jitter(width = 0.05))

#Veamos tambien si hay patrones para nuestras variables explicativas:


p2<-ggplot(data = ParasiteCod2, aes(fYear, y=E1))+
ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p3<-ggplot(data = ParasiteCod2, aes(fArea, y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p4<-ggplot(data = ParasiteCod2, aes(Length, y=E1)) +


stat_smooth(aes(x = Length, y = E1), method="gam") +
ylab("Pearson residuals") +
xlab("Length") +
geom_jitter(size=1,position = position_jitter(width = 0.05))

grid.arrange(p1,p2,p3,p4,ncol=2)

No se observan patrones ni outliers evidentes. Parece que podemos quedarnos con este
modelo.

Vamos a echarle un ojo a algunos de los coeficientes del modelo para interpretar su
significado:

summary(Zinb1)
##
## Call:
## zeroinfl(formula = f1, data = ParasiteCod2, dist = "negbin", link =
"logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.614 -0.443 -0.358 -0.125 11.453
##
## Count model coefficients (negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 3.73390 0.34440 10.84 <2e-16 ***
## fArea2 0.19777 0.32913 0.60 0.548
## fArea3 -0.64673 0.27779 -2.33 0.020 *
## fArea4 0.70750 0.25226 2.80 0.005 **
## fYear2000 0.06389 0.29564 0.22 0.829
## fYear2001 -0.93915 0.60606 -1.55 0.121
## Length -0.03641 0.00511 -7.13 1e-12 ***
## fArea2:fYear2000 -0.65399 0.53542 -1.22 0.222
## fArea3:fYear2000 1.02496 0.42960 2.39 0.017 *
## fArea4:fYear2000 0.53453 0.41497 1.29 0.198
## fArea2:fYear2001 0.96727 0.71817 1.35 0.178
## fArea3:fYear2001 1.00270 0.67750 1.48 0.139
## fArea4:fYear2001 0.85516 0.65440 1.31 0.191
## Log(theta) -0.96662 0.09634 -10.03 <2e-16 ***
##
## Zero-inflation model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.1909 0.7813 0.24 0.80697
## fArea2 2.0137 0.5729 3.51 0.00044 ***
## fArea3 1.9053 0.5499 3.46 0.00053 ***
## fArea4 -0.7362 0.8622 -0.85 0.39321
## fYear2000 -1.0717 2.0002 -0.54 0.59209
## fYear2001 3.2932 0.7104 4.64 3.6e-06 ***
## Length -0.0388 0.0120 -3.23 0.00125 **
## fArea2:fYear2000 0.4654 2.0789 0.22 0.82286
## fArea3:fYear2000 -0.7945 2.1576 -0.37 0.71269
## fArea4:fYear2000 -13.5700 1509.5741 -0.01 0.99283
## fArea2:fYear2001 -3.2074 0.8360 -3.84 0.00012 ***
## fArea3:fYear2001 -3.5041 0.8300 -4.22 2.4e-05 ***
## fArea4:fYear2001 -2.9105 1.1046 -2.63 0.00841 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta = 0.38
## Number of iterations in BFGS optimization: 53
## Log-likelihood: -2.45e+03 on 27 Df

Respecto a la parte del conteo del modelo:

 A igualdad de todo lo demás, el log(count) del número de parásitos del Area4


es 0.71 unidades mayor que la del Area1, lo que equivale a decir que esperamos
que un bacalao del Area4 tenga 2.03 parásitos más que uno del Area1.

-En el año 2000 la abundancia de parásitos fue mayor (a igualdad de todo lo demás).

-El número de parásitos desciende con el tamaño del bacalao (coeficiente de Length=-
0.036) a un ritmo de 0.96 parásitos por centímetro

Respecto a la parte binomial:

Atención a esto, que puede haber sorpresas!. Recuerda que la parte binomial del
modelo nos indica la probabilidad de que una observación sea un falso 0; esto quiere
decir que un coeficiente negativo indica que cuando esa variable toma un valor alto (o
no nulo en el caso de los factores) las probabilidades de observar falsos ceros
disminuyen. Por ejemplo:

 El coeficiente para Year2001 es 3.29. Es decir, a igualdad de otros factores, en el


año 2001 es más probable observar falsos ceros que en el año 1999 (que es el
nivel que sirve de base).
 El coeficiente para Length es de -0.039: la probabilidad de un falso 0 es menor
cuanto más grande sea el bacalao.
Cuidado con esto, porque en los modelos ZA(P/NB), la parte binomial nos da la
probabilidad de que una observación no sea 0, es decir, los coeficientes (además de
diferir algo) tendrán distinto signo.

Por lo general, una buena representación gráfica suele ayuda mucho a entender nuestros
modelos:

newdata1 <- expand.grid(factor(1:4), factor(1999:2001), 17:101) ##Con


esto creamos todas las combinaciones posibles de nuestros tres
predictores
colnames(newdata1) <- c("fArea", "fYear", "Length")
newdata1$predZI <- predict(Zinb1, newdata1) ##Calculamos lo que
predice nuestro modelo para cada combinacion de los predictores

ggplot(newdata1, aes(x = Length, y = predZI, colour = fYear)) +


geom_point() +
geom_line() +
facet_wrap(~fArea) +
labs(x = "Length", y = "Número de parásitos predichos")

Una cosa interesante es que podemos representar los valores predichos para cada una de
las dos partes del modelo. Por ejemplo, para los falsos ceros:

newdata1$pred0<-predict(Zinb1, newdata1,type="zero")

ggplot(newdata1, aes(x = Length, y = pred0, colour = fYear)) +


geom_point() +
geom_line() +
facet_wrap(~fArea) +
labs(x = "Length", y = "Probabilidad de falsos ceros")

Y para los conteos:

newdata1$predCount<-predict(Zinb1, newdata1,type="count")

ggplot(newdata1, aes(x = Length, y = predCount, colour = fYear)) +


geom_point() +
geom_line() +
facet_wrap(~fArea) +
labs(x = "Length", y = "Número de parásitos predichos (sin falsos
ceros)")

Observa que si le decimos a predict que type="count", el número de parásitos


predichos es mayor que el predicho por el modelo cuando tiene en cuenta los falsos
ceros. Como ya hemos visto antes, lo que hacemos al hacer un modelo ZI es modelizar
dos procesos distintos y combinarlos. En realidad, si lo expresamos en términos de las
tres predicciones que acabamos de crear:

predZI=predCount∗(1−pred0)
¿lo comprobamos?

newdata1$predZI== newdata1$predCount* (1- newdata1$pred0)


## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [14] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [27] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [40] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [53] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [66] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [79] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [92] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [105] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [118] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [131] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [144] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [157] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [170] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [183] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [196] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [209] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [222] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [235] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [248] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [261] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [274] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [287] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [300] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [313] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [326] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [339] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [352] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [365] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [378] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [391] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [404] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [417] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [430] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [443] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [456] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [469] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [482] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [495] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [508] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [521] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [534] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [547] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [560] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [573] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [586] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [599] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [612] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [625] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [638] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [651] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [664] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [677] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [690] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [703] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [716] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [729] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [742] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [755] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [768] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [781] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [794] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [807] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [820] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [833] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [846] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [859] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [872] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [885] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [898] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [911] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [924] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [937] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [950] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [963] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [976] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [989] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [1002] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
TRUE
## [1015] TRUE TRUE TRUE TRUE TRUE TRUE

Es decir, el valor obtenido aplicando el proceso de conteo es modulado (reducido) por el


proceso binomial (los falsos ceros). Esto tiene sentido: si para cierta combinación de
nuestros predictores el proceso de conteo predice un gran número de parásitos, pero a su
vez el proceso binomial predice una alta probabilidad de observar falsos ceros, nuestro
modelo va a predecir un número de parásitos más bien bajo. Fíjate por ejemplo en:

 la diferencia para la combinación Year2001:Area1, para la que la probabilidad


de predecir un falso cero es muy alta.
 el bajo número de parásitos predichos para Area2, que se debe en gran medida a
la alta probabilidad de registrar falsos ceros.
 la pequeña diferencia entre el resultado global y el del proceso de conteo para
Area4, en la que la probabilidad de medir falsos ceros es relativamente baja.

Referencias.

El texto y código está basado principalmente en:


 Zuur, A.F., Ieno, E. I., Walker, N.J., Saveliev, A. A., Smith, G. 2009. Mixed
Effects Models and Extensions in Ecology with R. Springer.
 http://www.ats.ucla.edu/stat/r/dae/zinbreg.htm
 http://www.ats.ucla.edu/stat/r/dae/zipoisson.htm

SOLUCIÓN al Prueba tú mismo #2:

############################################
######### SELECCION DE VARIABLES
############################################

fA1<-formula(count ~ adultos + child + camper + adultos:camper +


camper:child |
adultos + child + camper + adultos:child + adultos:camper
+ camper:child)

fB1<-formula(count ~ adultos + child + camper + adultos:child+


adultos:camper + camper:child |
adultos + child + camper + adultos:camper + camper:child)

ZanbA1<- hurdle(fA1, dist = "negbin",link = "logit", data = fish)


ZanbB1<- hurdle(fB1, dist = "negbin",link = "logit", data = fish)

lrtest(Zanb1,ZanbA1)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + adultos:child + adultos:camper +
## camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 15 -390
## 2 14 -390 -1 0.21 0.65
lrtest(Zanb1,ZanbB1)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:child +
## adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:camper +
## camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 15 -390
## 2 14 -390 -1 0.15 0.69
AIC(Zanb1,ZanbA1,ZanbB1)
## df AIC
## Zanb1 15 810.7
## ZanbA1 14 808.9
## ZanbB1 14 808.8
#Me quedo con ZanbB1
summary(ZanbB1)
##
## Call:
## hurdle(formula = fB1, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.76166 -0.50910 -0.29333 -0.00914 9.10048
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.512 0.867 -1.74 0.0810 .
## adultos 0.850 0.291 2.92 0.0035 **
## child 1.309 0.952 1.38 0.1688
## camper 0.358 0.933 0.38 0.7012
## adultos:child -0.169 0.366 -0.46 0.6446
## adultos:camper 0.214 0.335 0.64 0.5227
## child:camper -1.445 0.702 -2.06 0.0397 *
## Log(theta) -0.808 0.430 -1.88 0.0599 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.6988 0.6127 -2.77 0.00556 **
## adultos 0.8963 0.2862 3.13 0.00174 **
## child -1.4781 0.4390 -3.37 0.00076 ***
## camper -0.0475 0.7864 -0.06 0.95182
## adultos:camper 0.4150 0.3909 1.06 0.28839
## child:camper 0.6909 0.5207 1.33 0.18458
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.446
## Number of iterations in BFGS optimization: 17
## Log-likelihood: -390 on 14 Df
fA2<-formula(count ~ adultos + child + camper + adultos:camper +
camper:child |
adultos + child + camper + adultos:camper + camper:child)

fB2<-formula(count ~ adultos + child + camper + adultos:child+


adultos:camper + camper:child |
adultos + child + camper + camper:child)
ZanbA2<- hurdle(fA2, dist = "negbin",link = "logit", data = fish)
ZanbB2<- hurdle(fB2, dist = "negbin",link = "logit", data = fish)

lrtest(ZanbB1,ZanbA2)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:camper +
## camper:child
## Model 2: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + adultos:camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 14 -390
## 2 13 -391 -1 0.21 0.65
lrtest(ZanbB1,ZanbB2)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + adultos:camper +
## camper:child
## Model 2: count ~ adultos + child + camper + adultos:child +
adultos:camper +
## camper:child | adultos + child + camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 14 -390
## 2 13 -391 -1 1.12 0.29
AIC(ZanbB1,ZanbA2,ZanbB2)
## df AIC
## ZanbB1 14 808.8
## ZanbA2 13 807.0
## ZanbB2 13 807.9
#Me quedo con ZanbA2
summary(ZanbA2)
##
## Call:
## hurdle(formula = fA2, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.7605 -0.5081 -0.3043 -0.0458 9.0018
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.504 0.872 -1.73 0.0844 .
## adultos 0.844 0.292 2.89 0.0038 **
## child 0.979 0.625 1.57 0.1174
## camper 0.425 0.927 0.46 0.6465
## adultos:camper 0.187 0.330 0.57 0.5715
## child:camper -1.474 0.706 -2.09 0.0367 *
## Log(theta) -0.823 0.432 -1.90 0.0569 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.6988 0.6127 -2.77 0.00556 **
## adultos 0.8963 0.2862 3.13 0.00174 **
## child -1.4781 0.4390 -3.37 0.00076 ***
## camper -0.0475 0.7864 -0.06 0.95182
## adultos:camper 0.4150 0.3909 1.06 0.28839
## child:camper 0.6909 0.5207 1.33 0.18458
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.439
## Number of iterations in BFGS optimization: 17
## Log-likelihood: -391 on 13 Df
fA3<-formula(count ~ adultos + child + camper + camper:child |
adultos + child + camper + adultos:camper + camper:child)

fB3<-formula(count ~ adultos + child + camper + adultos:camper +


camper:child |
adultos + child + camper + camper:child)
ZanbA3<- hurdle(fA3, dist = "negbin",link = "logit", data = fish)
ZanbB3<- hurdle(fB3, dist = "negbin",link = "logit", data = fish)

lrtest(ZanbA2,ZanbA3)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + adultos:camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 13 -391
## 2 12 -391 -1 0.31 0.58
lrtest(ZanbA2,ZanbB3)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + adultos:camper +
camper:child |
## adultos + child + camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 13 -391
## 2 12 -391 -1 1.12 0.29
AIC(ZanbA2,ZanbA3,ZanbB3)
## df AIC
## ZanbA2 13 807.0
## ZanbA3 12 805.3
## ZanbB3 12 806.1
#Me quedo con ZanbA3
summary(ZanbA3)
##
## Call:
## hurdle(formula = fA3, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.7577 -0.5229 -0.3030 -0.0455 8.8784
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.888 0.562 -3.36 0.00079 ***
## adultos 0.990 0.146 6.76 1.4e-11 ***
## child 1.072 0.609 1.76 0.07818 .
## camper 0.903 0.368 2.45 0.01425 *
## child:camper -1.585 0.683 -2.32 0.02032 *
## Log(theta) -0.848 0.436 -1.94 0.05202 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.6988 0.6127 -2.77 0.00556 **
## adultos 0.8963 0.2862 3.13 0.00174 **
## child -1.4781 0.4390 -3.37 0.00076 ***
## camper -0.0475 0.7864 -0.06 0.95182
## adultos:camper 0.4150 0.3909 1.06 0.28839
## child:camper 0.6909 0.5207 1.33 0.18458
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.428
## Number of iterations in BFGS optimization: 14
## Log-likelihood: -391 on 12 Df
fA4<-formula(count ~ adultos + child + camper |
adultos + child + camper + adultos:camper + camper:child)
fB4<-formula(count ~ adultos + child + camper + camper:child |
adultos + child + camper + camper:child)
ZanbA4<- hurdle(fA4, dist = "negbin",link = "logit", data = fish)
ZanbB4<- hurdle(fB4, dist = "negbin",link = "logit", data = fish)

lrtest(ZanbA3,ZanbA4)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper | adultos + child +
camper +
## adultos:camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 12 -391
## 2 11 -394 -1 5.68 0.017 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
lrtest(ZanbA3,ZanbB4)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + adultos:camper + camper:child
## Model 2: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 12 -391
## 2 11 -391 -1 1.12 0.29
AIC(ZanbA3,ZanbA4,ZanbB4)
## df AIC
## ZanbA3 12 805.3
## ZanbA4 11 809.0
## ZanbB4 11 804.5
#Me quedo con ZanbB4
summary(ZanbB4)
##
## Call:
## hurdle(formula = fB4, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.7519 -0.4814 -0.3186 -0.0228 9.0014
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.888 0.562 -3.36 0.00079 ***
## adultos 0.990 0.146 6.76 1.4e-11 ***
## child 1.072 0.609 1.76 0.07818 .
## camper 0.903 0.368 2.45 0.01425 *
## child:camper -1.585 0.683 -2.32 0.02032 *
## Log(theta) -0.848 0.436 -1.94 0.05202 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.143 0.470 -4.56 5.1e-06 ***
## adultos 1.135 0.194 5.86 4.7e-09 ***
## child -1.546 0.457 -3.38 0.00072 ***
## camper 0.681 0.396 1.72 0.08590 .
## child:camper 0.757 0.533 1.42 0.15539
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.428
## Number of iterations in BFGS optimization: 14
## Log-likelihood: -391 on 11 Df
fA5<-formula(count ~ adultos + child + camper |
adultos + child + camper + camper:child)

fB5<-formula(count ~ adultos + child + camper + camper:child |


adultos + child + camper )
ZanbA5<- hurdle(fA5, dist = "negbin",link = "logit", data = fish)
ZanbB5<- hurdle(fB5, dist = "negbin",link = "logit", data = fish)

lrtest(ZanbB4,ZanbA5)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + camper:child
## Model 2: count ~ adultos + child + camper | adultos + child +
camper +
## camper:child
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 11 -391
## 2 10 -394 -1 5.68 0.017 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
lrtest(ZanbB4,ZanbB5)
## Likelihood ratio test
##
## Model 1: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper + camper:child
## Model 2: count ~ adultos + child + camper + camper:child | adultos
+ child +
## camper
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 11 -391
## 2 10 -392 -1 2.18 0.14
AIC(ZanbB4,ZanbA5,ZanbB5) #Cuidadito aqui... LRT y AIC difieren...
sigo con LRT, a ver que tal:
## df AIC
## ZanbB4 11 804.5
## ZanbA5 10 808.1
## ZanbB5 10 804.6
#Me quedo con ZanbB5
summary(ZanbB5) #Todo es significativo. Ya hemos acabado la selección
##
## Call:
## hurdle(formula = fB5, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.7483 -0.5001 -0.2918 -0.0694 8.0265
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.888 0.562 -3.36 0.00079 ***
## adultos 0.990 0.146 6.76 1.4e-11 ***
## child 1.072 0.609 1.76 0.07818 .
## camper 0.903 0.368 2.45 0.01425 *
## child:camper -1.585 0.683 -2.32 0.02032 *
## Log(theta) -0.848 0.436 -1.94 0.05202 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.309 0.461 -5.01 5.6e-07 ***
## adultos 1.110 0.191 5.81 6.2e-09 ***
## child -1.028 0.234 -4.40 1.1e-05 ***
## camper 1.018 0.325 3.14 0.0017 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.428
## Number of iterations in BFGS optimization: 14
## Log-likelihood: -392 on 10 Df
############################################
######### VALIDACION
############################################
E1<- residuals(ZanbB5, type="pearson")
F1<- predict(ZanbB5, type="response")

p1<-ggplot(data = NULL, aes(x=F1, y=E1)) +


stat_smooth(aes(x = F1, y = E1), method="gam") +
ylab("Pearson residuals") +
xlab("Fitted values") +
geom_jitter(size=1,position = position_jitter(width = 0.05))

#Veamos tambien si hay patrones para nuestras variables explicativas:


p2<-ggplot(data = fish, aes(factor(adultos), y=E1))+
ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p3<-ggplot(data = fish, aes(factor(child), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

p4<-ggplot(data = fish, aes(factor(camper), y=E1)) +


ylab("Pearson residuals") +
stat_boxplot()+
geom_hline(h=0, colour=2)

grid.arrange(p1,p2,p3,p4,ncol=2)

############################################
######### INTERPRETACIÓN
############################################

summary(ZanbB5)
##
## Call:
## hurdle(formula = fB5, data = fish, dist = "negbin", link = "logit")
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## -0.7483 -0.5001 -0.2918 -0.0694 8.0265
##
## Count model coefficients (truncated negbin with log link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.888 0.562 -3.36 0.00079 ***
## adultos 0.990 0.146 6.76 1.4e-11 ***
## child 1.072 0.609 1.76 0.07818 .
## camper 0.903 0.368 2.45 0.01425 *
## child:camper -1.585 0.683 -2.32 0.02032 *
## Log(theta) -0.848 0.436 -1.94 0.05202 .
## Zero hurdle model coefficients (binomial with logit link):
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.309 0.461 -5.01 5.6e-07 ***
## adultos 1.110 0.191 5.81 6.2e-09 ***
## child -1.028 0.234 -4.40 1.1e-05 ***
## camper 1.018 0.325 3.14 0.0017 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Theta: count = 0.428
## Number of iterations in BFGS optimization: 14
## Log-likelihood: -392 on 10 Df
##### proceso binomial (Distingue entre grupos que pescan algo y lo
que no pescan nada):
# Los grupos con más niños tienen menos probabilidades de pescar algo
(coeficiente de child negativo)
# Cuantos más adultos haya, más probabilidades hay de pescar algo.
# Los grupos que van en caravana tienen más probabilidades de pescar
algo.

##### proceso conteo (predice el número de peces pescados por los


grupos que pescan algo):
# Cuantos más adultos, más se pesca.
# Los grupos que van en caravana pescan más que los que no.
# Cuantos más niños, más se pesca (ojo, p>0.05, no podemos estar muy
seguros de esto). En cambio,
# si se va en caravana, cuantos más niños se lleven, menos se pesca.

### Representación gráfica:

newdata1 <- expand.grid(unique(fish$adultos), unique(fish$child),


unique(fish$camper)) ##Con esto creamos todas las combinaciones
posibles de nuestros tres predictores
colnames(newdata1) <- c("adultos", "child", "camper")
newdata1$predZANB <- predict(ZanbB5, newdata1) ##Calculamos lo que
predice nuestro modelo para cada combinacion de los predictores

ggplot(newdata1, aes(x = adultos, y = predZANB, colour =


factor(child))) +
geom_point() +
geom_line() +
facet_wrap(~camper) +
labs(x = "Adultos", y = "Número de peces predichos")

##¡¡Cuidado con esta figura, que es engañosa!! En realidad no hay


grupos con 4 adultos y 3 niños. El máximo de personas en un grupo es
más bajo:

max(fish$adultos+fish$child)
## [1] 4
##Luego esta predicción es una extrapolación para la que no tenemos
datos suficientes. Limitemos las predicciones a las combinaciones que
sabemos que existen:

fish$predZANB <- predict(ZanbB5)

ggplot(fish, aes(x = adultos, y = predZANB, colour = factor(child))) +


geom_point() +
geom_line() +
facet_wrap(~camper) +
labs(x = "Adultos", y = "Número de peces predichos")

Paquetes empleados:

Este documento html está confeccionado con R-Markdown desde RStudio 0.98.978. El
código está hecho con R version 3.1.1 (2014-07-10) así como con los paquetes ggplot2
1.0.0, VGAM 0.9.4, gridExtra 0.9.1, lattice 0.20.29, pscl 1.4.6, lmtest 0.9.33 y MASS
7.3.33

Versión de: [1] “2014-09-04 17:29:26 CEST”

También podría gustarte