Documentos de Académico
Documentos de Profesional
Documentos de Cultura
regresión en R
1. Introducción
2. Modelos truncados por ceros
3b1. Poisson
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.
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” μ
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 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.
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
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
f(0;μi)=μ0 e−μi0!=e−μi
;
recuerda: 0! = 1 ;-)
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
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 μ
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))
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:
Parece que:
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
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
).
Empezemos ajustando un glm Poisson truncado por ceros. Para usar este tipo de
modelos, vamos a cargar el paquete VGAM (que habrá que instalar):
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.
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!):
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
E(Y)=μ
var(Y)=μ+α∗μ2
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:
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:
Ahora viene la mejor parte: interpretar nuestro modelo. Recordemos que las VEs que
han “resistido” nuestro escrutinio han sido:
¿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:
…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”:
¡10.63 días!
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
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.
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:
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:
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.
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).
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.
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).
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:
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 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:
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.
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
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:
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…)
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.
ZANB
La mejor forma de ver si elegimos el modelo ZAP o el ZANB es ajustar ambos modelos
(saturados) y compararlos:
En efecto, todo indica que Zanb1 es mucho mejor. De nuevo, vamos a seleccionar las
variables explicativas.
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
Antes de nada, vamos a decirle a R que tanto Area como Year son factores, y no
variables cuantitativas.
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, ]
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?
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.
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 π
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:
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
y βpoi
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.
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:
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:
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.
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)
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.
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
-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
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:
Por lo general, una buena representación gráfica suele ayuda mucho a entender nuestros
modelos:
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")
newdata1$predCount<-predict(Zinb1, newdata1,type="count")
predZI=predCount∗(1−pred0)
¿lo comprobamos?
Referencias.
############################################
######### SELECCION DE VARIABLES
############################################
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)
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)
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)
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")
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.
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:
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