Modelos Estadísticos. Grado Biotecnología
Abstract
En este tema se introducen los modelos de regresión de Poisson.Son frecuentes los datos discretos que provienen de conteos de sucesos que se producen por azar con cierta frecuencia y son modelizables en términos de tasas de incidencia que dependen de ciertas variables explicativas. Para modelizar este tipo de datos se utiliza la distribución de Poisson, \(X \sim Po(\mu)\), donde \(\mu\) representa el número medio de ocurrencias, de forma que: \[E(X) = \mu \text{ y } V(X) = \mu.\]
El parámetro \(\mu\) requiere una definición cuidadosa. A menudo es necesario describirlo como una tasa; por ejemplo, el número promedio de clientes que compran un particular producto de cada 100 clientes que ingresan a la tienda. De manera más general, la tasa se especifica en términos de unidades de “exposición” o en términos de años-persona ‘en riesgo’, por ejemplo, el número de personas que sufren cierta enfermedad sobre el total de personas para un instante de tiempo determinado. El efecto de las variables predictoras sobre la respuesta se modeliza valorando su efecto sobre \(\mu\).
Sea \(Y_1, Y_2,..., Y_n\) un conjunto de variables aleatorias Poisson, donde \(Y_i\) representa el número de eventos observados a partir de la exposición \(n_i\) para el i-esimo patrón de covariables. En esta situación el valor esperado de \(Y_i\) se puede escribir como: \[E(Y_i) = \mu_i = n_i \lambda_i,\] donde \(\lambda_i\) representa la tasa de incidencia para el patrón i-ésimo.
Veamos dos situaciones prácticas:
breaks
(número de roturas), wool
(tipo de lana), y tension
(tensión de la lana). La pregunta de interés es si ¿resulta posible predecir el número de roturas en función del tipo de lana y de la tensión?En este caso la exposición a riesgo es constante (\(n_i =1\)), y por tanto se considera que las posibles predictoras influyen directamente sobre \(\mu_i = breaks_i\)
type
(el tipo de barco, codificado de A hasta E), year
(el año de construcción del barco en los periodos 1960–64, 65–69, 70–74, 75–79 codificados como 60, 65, 70, 75), period
(período de operación del barco 1960-74, 75-79 codificados como 60, 75), service
(meses de servicio), incidents
(número de incidentes)En este caso la exposición a riesgo no es constante, ya que caunto mayor sea el tiempo de servicio de un barco parece más probable que sufra un incidente. En este caso \(n_i = service_i\) y modelizamos la tasa de riesgo \(\lambda_i\) con la información de las variables predictoras. En la práctica \(\lambda_i = incidents_i/service_i\) y represetamos dicha variable con respecto a las predictoras para el planteamiento del modelo.
El modelo lineal generalizado para variables aleatorias Poisson o más conocido como regresión de Poisson se puede especificar siguiendo la definición establecida en el punto anterior como:
En esta situación y tomando como función de enlace el logaritmo tenemos que: \[log(E(Y_i)) = log(\mu_i) = log(n_i\lambda_i) = log(n_i) + log(\lambda_i)= log(n_i) + \beta_0 + \beta_1 x_{i1} + \beta_2 x_{i2} + ...+ \beta_p x_{ip}\]
donde tenemos la expresión del modelo lineal generalizado. La única diferencia de este modelo con los vistos hasta ahora es la inclusión de un término fijo en el modelo (\(log(n_i)\)) que actúa como “offset” y hace referencia al logaritmo de sujetos en riesgo para la combinación de predictoras correspondiente al índice \(i\). Este términos se debe incorporar en la estimación del modelo como una constante para cada \(i\). Para el ejemplo de las telas cada \(n_i = 1\) y cada \(log(n_i) = 0\) desapareciendo de la estimación del modelo. En el caso de los barcos tenemos que \(log(n_i) = log(service_i)\) remarcando el hecho de que el riesgo aumenta cuando lo hace el tiempo de servicio. El offset no se puede estimar ya que es fijo, y la estimación del modelo se centra únicamente en los parámetros asociados con cada una de las predictoras.
Respecto de la interpretación de dichos coeficientes se puede demostrar que \(exp(\beta_j)\) representa el riesgo relativo (\(RR\)) sobre la tasa de incidencia de los sucesos asociado a un incremento de una unidad en la covariable \(x_j\). Es similar a la interpretación que hacíamos en los modelos lineales, salvo el cambio de escala debido a la transformación logaritmo sobre la media de la respuesta.
Para una variable de tipo numérico se define el riesgo relativo al incrementar una unidad el valor de la variable predictora \(X\) como: \[RR(X) = \frac{\lambda(X = x+1)}{\lambda(X = x+1)} = exp(\beta_x)\] mientras que riesgo relativo para valorar el cambio entre dos niveles de una variable categórica (A y B) se define como:
\[RR(X_{AB}) = \frac{\lambda(X = B)}{\lambda(X = A)} = exp(\text{coeficiente asociado a B} - \text{coeficiente asociado a A})\]
El riesgo relativo aumenta cuando \(RR > 1\) y disminuye cuando \(RR < 1\). Tenemos el mismo riesgo cuando \(RR = 1\)
En este punto realizamos un análisis preliminar de los bancos de datos de los ejemplos para estudiar el comportamiento de la tasa de incidencia con respecto a cada predictora y determinar los posible modelos a considerar en la fase de estimación. En primer lugar cargamos las librerías de trabajo
Comenzamos con la lectura del banco de datos y realizamos un estudio descriptivo inicial
require(datasets)
glm_poi_01 <- warpbreaks
# Descriptivo
summary(glm_poi_01)
## breaks wool tension
## Min. :10.00 A:27 L:18
## 1st Qu.:18.25 B:27 M:18
## Median :26.00 H:18
## Mean :28.15
## 3rd Qu.:34.00
## Max. :70.00
En este tipo de modelos es muy habitual trabajar con variables categóricas de tipo ordinal. Dichas varaible spueden ser incorporadas en el modelo como factores pero en ocasiones interesa introducirlas como numéricas para captar las posibles tendencias de la respuesta conforme aumneta la relevancia del factor. Recordemos que una variable categórica ordinal se puede obtener siempre a partir de una variable de tipo numérico. Para poder hacer esto introducimos un código numérico artificial asociado con cada categoría. Disponemos de dos alternativas:
1. Asignar un código continuo: 1, 2, 3,… donde los valores más bajos se asocian con los niveles más bajos de la variable categórica.
2. Cuando la variable categórica viene dada en términos de un intervalo se puee usar el punto medio de dicho intervalo para establecer el código numerico
En este caso optamos por asignar un código continuo:
# Creamos varuables par acada categoria con su código numérico. Construimos la variable conjunta y
# nos quedamos sólo con las variables de interés
glm_poi_01 <- glm_poi_01 %>%
mutate(t1 = ifelse(tension == "L",1,0)) %>%
mutate(t2 = ifelse(tension == "M",2,0)) %>%
mutate(t3 = ifelse(tension == "H",3,0)) %>%
mutate(tension.num = t1+t2+t3)
# Selecionamos el conjunto de variables final
glm_poi_01 <- glm_poi_01[,c("breaks","wool","tension","tension.num")]
Representamos la incidencia (en este caso \(n_i = 1\)) que corresponde con la variable breaks
, es decir, representamos el logaritmo de la incidencia con respecto a las predictoras, para valorar la linealidad del efecto.
# Utilizamos las dos varible categóricas
ggplot(glm_poi_01,aes(x = tension, y = log(breaks), color = wool)) + geom_boxplot() + theme_bw()
En el gráfico se aprecia cierta tendencia con la tensión, pero no tanto con el tipo de lana. Realizamos el gráfico de interacción con las medias para las combinaciones de ambos factores.
ggplot(glm_poi_01, aes(x = tension, y = log(breaks), group = wool, color = wool)) +
stat_summary(fun.y = mean, geom = "point") +
stat_summary(fun.y = mean, geom = "line") +
theme_bw()
Se puede ver un efecto conjunto entre tension
y wool
. Parece bastante claro que deberemos considerar un efecto de interacción para este modelo. De hecho, se aprecian curvas descendientes con tension
(indicando que las telas sufren menos roturas a mayor tensión) no apreciándose efecto lineal lo que puede provocar que no se verifiquen las hipótesis del modelo, y que sea necesario introducir ciertos tendencias en las variables predictoras. En el tipo de lana resulta imposible hacer esto porque es una variable categórica nominal, pero si podríamos hacerlo con tension
si la consideramos como numérica a partir de los códigos introducidos para cada categoría. Ajustaremos ambos modelos y decidiremos cual de ellos produce resultados más interesantes.
Comenzamos con la lectura del banco de datos y realizamos un estudio descriptivo inicial
require(MASS)
glm_poi_07 <- ships
# generamos factores a partir de los códigos numéricos
glm_poi_07$year.f <- as.factor(glm_poi_07$year)
glm_poi_07$period.f <- as.factor(glm_poi_07$period)
summary(glm_poi_07)
## type year period service incidents
## A:8 Min. :60.00 Min. :60.0 Min. : 0.0 Min. : 0.0
## B:8 1st Qu.:63.75 1st Qu.:60.0 1st Qu.: 175.8 1st Qu.: 0.0
## C:8 Median :67.50 Median :67.5 Median : 782.0 Median : 2.0
## D:8 Mean :67.50 Mean :67.5 Mean : 4089.3 Mean : 8.9
## E:8 3rd Qu.:71.25 3rd Qu.:75.0 3rd Qu.: 2078.5 3rd Qu.:11.0
## Max. :75.00 Max. :75.0 Max. :44882.0 Max. :58.0
## year.f period.f
## 60:10 60:20
## 65:10 75:20
## 70:10
## 75:10
##
##
Como se puede ver en el resumen hay barcos que tiene 0 meses de servicio, y por tanto deben ser eliminados del análisis, ya que al tratar de ajustar la tasa dividiríamos por un valor de 0, lo que provocaría la imposibilidad de un ajuste adecuado. Seleccionamos todos los barcos con tiempo de servicio mayor que cero y obtenemos la tasa de incidencia a partir de la relación entre el número de incidentes y las horas de servicio de cada barco.
glm_poi_07 <- glm_poi_07 %>%
filter(service>0) %>%
mutate(tasa = incidents/service)
Realizamos el gráfico de la media del logaritmo de la tasa para type
, year
y period
. En realidad trabajamos con los factores para representar adecuadamente el gráfico de interacción.
ggplot(glm_poi_07, aes(x = year.f, y = log(tasa), group = period.f, color = period.f)) +
stat_summary(fun.y = mean, geom = "point") +
stat_summary(fun.y = mean, geom = "line") +
facet_grid(~type) +
theme_bw()
Se observa que los tipos de barco se comportan de forma diferente en cuanto a la tasa de incidentes. Los barcos del tipo “E” son los que tienen tasas más altas. En cuanto al año de fabricación y el periodo de funcionamiento varían con el tipo de barco. Mientras que para los tipos “A” y “B” se observan comportamientos muy similares no ocurre los mismo para el tipo “C”. De nuevo habrá que vigilar el efecto para asegurar la linealidad del GLM.
En este caso nos podemos plantear un modelo con tres predictoras de tipo factor y considerar sus posible interacciones (lo que nos da un modelo bastante complejo), u optar por un modelo más sencillo donde consideramos year
y period
como numéricas. Obtenemos la tabla cruzada de ambos factores para ver si hay alguna combinación que no se da, y por tanto desechar el modelo a que darían lugar.
table(glm_poi_07$year.f,glm_poi_07$period.f)
##
## 60 75
## 60 5 4
## 65 5 5
## 70 5 5
## 75 0 5
Se observa que la combinación year_f 75 y period_f 60 no tienen ningún dato. Si consideramos la interacción de ambos factores en el modelo obtendremos un error ya que no disponemos de datos para esa combinación. Procedemos por tanto a considerarlas como numéricas para evitar esos problemas con la estimación del modelo.
Como hemos hecho hasta ahora, en un primer momento estimamos el modelo más complejo posible para proceder posteriormente con la selección de aquellos efectos que de verdad resultan significativos. Para la estimación utilizamos la función glm
con las especificaciones siguientes:
glm(modelo,family = poisson, offset = value, data_set)
La diferencia principal con los modelos de regresión logística es la introducción de los offsets en el ajuste del modelo. Si no disponemos de offsets (como en el ejemplo de la lana) no aparecerán en el ajuste del modelo.
Para este banco de datos ajustamos dos modelos completos considerando la tensión como factor o como variable numérica. Comenzamos con el modelo considerando todas las predictoras como factores. Consideramos tanto los efectos asociados a cada factor como la posible interacción entre ellos. En este caso no hay offsets. El modelo propuesto es: \[breaks \sim wool*tension\]
telas.cat <-glm(breaks ~ wool*tension,family = poisson, glm_poi_01)
# Resumen del modelo
summary(telas.cat)
Los coeficientes del modelo resultan significativos salvo en al combinación wool B y tension H. Ajustamos ahora el otro modelo asumiendo la variable tensión con el código numérico: \[breaks \sim wool*tension.num\]
telas.num <-glm(breaks ~ wool*tension.num,family = poisson, glm_poi_01)
# Resumen del modelo
summary(telas.num)
Los coeficientes del modelo resultan significativos pero el valor del AIC es superior al del modelo con los dos factores. Por el momento, nos quedamos con el modelo telas.cat
y escribimos las expresiones de dicho modelo:
\[\left\{\begin{array}{lll} log(breaks)_{woolA;tensionL} & = 3.79674 & \to exp(3.79674) = 44.6\\ log(breaks)_{woolA;tensionM} & = 3.79674 - 0.61868 = 3.17806 & \to exp(3.17806) = 24.0\\ log(breaks)_{woolA;tensionH} & = 3.79674 - 0.59580 = 3.20094 & \to exp(3.20094) = 24.6\\ log(breaks)_{woolB;tensionL} & = 3.79674 - 0.45663 = 3.34011 & \to exp(3.34011) = 28.2\\ log(breaks)_{woolB;tensionM} & = 3.79674 - 0.45663 - 0.61868 + 0.63818 = 3.35961 & \to exp(3.35961) = 28.8\\ log(breaks)_{woolB;tensionH} & = 3.79674 - 0.45663 - 0.59580 + 0.18836 = 2.93267 & \to exp(2.93267) = 18.8\\ \end{array}\right.\]
El proceso de estimación nos proporciona que el mayor número de roturas se produce para la combinación wool = A y tensión = L, mientras que el menor número se estima para la combinación wool = B y tensión = H.
Ajustamos el modelo utilizando las variables con los códigos numéricos en lugar de los factores. En este caso si disponemos de offset y el modelo planteado viene dado por: \[incidents \sim offset(service) + type *(year + period)\]
barcos.num <-glm(incidents ~ type *(year + period),family = poisson, offset = log(service), glm_poi_07)
# Resumen del modelo
summary(barcos.num)
El modelo presenta muchos coeficientes que parecen no significativos, y por tanto dejamos la interpretación hasta la selección del modelo definitivo.
Para la construcción del mejor modelo utilizaremos los mismos procedimientos que presentamos en el tema de regresión logística. Estudiamos a continuación cada uno de los ejemplos.
Utilizamos el modelo con los dos factores. Dado que existe un efecto de interacción, el proceso de selección debe establecer si es posible prescindir de dicho efecto, o si por otro debemos considerarlo en el modelo.
telas.cat <-glm(breaks ~ wool*tension,family = poisson, glm_poi_01)
# Resumen del modelo
step(telas.cat, test = "Chisq")
telas.fit <- telas.cat
Se puede ver que tanto el AIC con la significatividad el test indican que el efecto de interacción no puede ser eliminado del modelo. La conclusión es que para predecir el número de roturas debemos tener en cuenta las posibles combinaciones que se producen al mezclar los tipos de lana y su tensión (comportamientos distintos en cada combinación). El resumen del modelo es el obtenido en el punto anterior.
Sin embargo, con las ecuaciones estimadas anteriormente podemos construir las comparaciones de riesgo de rotura entre los tipos de tela o entre las diferentes tensiones que nos proporcionan una medida más realista del riesgo relativo (\(RR\)) de cada combinación. Por ejemplo:
\[RR_{AB;tensionL} = \frac{\lambda_{woolB;tensionL}}{\lambda_{woolA;tensionL}} = exp(3.17806 - 3.79674) = 0.54\]
\[RR_{LHC;woolA} = \frac{\lambda_{woolA;tensionH}}{\lambda_{woolA;tensionL}} = exp(3.20094 - 3.79674) = 0.55\]
\[RR_{LHC;woolB} = \frac{\lambda_{woolB;tensionH}}{\lambda_{woolB;tensionL}} = exp(2.93267 - 3.34011) = 0.66\]
En este caso los riesgos relativos estimados se pueden obtener a partir de la predicción del predictor lineal una vez hemos desecho la transformación logaritmo.
Tomamos como modelo de partida el que considera las variables de clasificación con sus códigos numéricos (las tratamos como numéricas). De nuevo debemos valorar la presencia o no de las interacciones entre el tipo de barco y las variables codificadas.
barcos.num <-glm(incidents ~ type *(year + period),family = poisson, offset = log(service), glm_poi_07)
step(barcos.num, test = "Chisq")
## Start: AIC=167
## incidents ~ type * (year + period)
##
## Df Deviance AIC LRT Pr(>Chi)
## - type:period 4 45.138 165.00 6.0015 0.199039
## <none> 39.136 167.00
## - type:year 4 54.046 173.91 14.9095 0.004893 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Step: AIC=165
## incidents ~ type + year + period + type:year
##
## Df Deviance AIC LRT Pr(>Chi)
## <none> 45.138 165.00
## - type:year 4 59.375 171.24 14.2369 0.006576 **
## - period 1 54.589 172.46 9.4517 0.002110 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Call: glm(formula = incidents ~ type + year + period + type:year, family = poisson,
## data = glm_poi_07, offset = log(service))
##
## Coefficients:
## (Intercept) typeB typeC typeD typeE
## -9.40739 -1.99170 -4.80174 2.57742 13.61537
## year period typeB:year typeC:year typeD:year
## 0.03166 0.02474 0.02134 0.06103 -0.03907
## typeE:year
## -0.19193
##
## Degrees of Freedom: 33 Total (i.e. Null); 23 Residual
## Null Deviance: 146.3
## Residual Deviance: 45.14 AIC: 165
barcos.fit <- glm(incidents ~ type + year +period + type:year,family = poisson, offset = log(service), glm_poi_07)
El proceso de selección de efectos indica que la interacción type:period
no es relevante para el modelo considerado ya que su eliminación disminuye la deviance y además el test resulta no significativo (pvalor = 0.1990). En principio es el único efecto que puede ser eliminado del modelo. El resumen del modelo final obtenido es:
summary(barcos.fit)
##
## Call:
## glm(formula = incidents ~ type + year + period + type:year, family = poisson,
## data = glm_poi_07, offset = log(service))
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.0704 -1.1705 -0.2069 0.4373 2.7276
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -9.407387 3.016649 -3.118 0.00182 **
## typeB -1.991695 3.124006 -0.638 0.52377
## typeC -4.801741 5.647285 -0.850 0.39517
## typeD 2.577417 4.878123 0.528 0.59725
## typeE 13.615368 4.911409 2.772 0.00557 **
## year 0.031664 0.042913 0.738 0.46059
## period 0.024744 0.008074 3.065 0.00218 **
## typeB:year 0.021342 0.044519 0.479 0.63166
## typeC:year 0.061030 0.081800 0.746 0.45561
## typeD:year -0.039075 0.068676 -0.569 0.56938
## typeE:year -0.191928 0.071220 -2.695 0.00704 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 146.328 on 33 degrees of freedom
## Residual deviance: 45.138 on 23 degrees of freedom
## AIC: 165
##
## Number of Fisher Scoring iterations: 6
Las conclusiones de este modelo son:
Veamos las ecuaciones estimadas (reducimos los decimales para una mejor visualización) para cada tipo de barco \[\left\{\begin{array}{ll} log(\lambda_{typeA}) & = -9.41 + 0.03*year + 0.02*period\\ log(\lambda_{typeB}) & = (-9.41 - 1.99) + (0.03 + 0.02)*year + 0.02*period\\ log(\lambda_{typeC}) & = (-9.41 - 4.80) + (0.03 + 0.06)*year + 0.02*period\\ log(\lambda_{typeD}) & = (-9.41 + 2.58) + (0.03 - 0.04)*year + 0.02*period\\ log(\lambda_{typeE}) & = (-9.41 + 13.62) + (0.03 - 0.19)*year + 0.02*period\\ \end{array}\right.\]
Comparamos ahora los riesgos de diferentes situaciones:
\[RR_{AE} = \frac{\lambda_{typeE}}{\lambda_{typeA}} = exp(\{4.21 - 0.16*year +0.02*period\} - \{-9.41 + 0.03*year + 0.02*period\})\] \[\text{de forma que } RR_{AE} = exp(13.62 - 0.19*year)\] Vemos el comportamiento del riesgo representándolo gráficamente con respecto al año de fabricación:
# Representamos dicho riesgo relativo
anyo <- seq(60,75,0.5)
riesgo <- exp(13.62 - 0.19*anyo)
datos <- data.frame(anyo,riesgo)
ggplot(datos,aes(x = anyo, y = riesgo)) +
geom_line() +
labs(x = "Año fabricación", y = "Riesgo Relativo", title ="Tipo E versus Tipo A") +
theme_bw()
El riesgo relativo de tener un incidente disminuye conforme aumenta el año de fabricación, pero para los instantes iniciales (año 60) el riesgo de los barcos de tipo E es más de siete veces superior al de los barcos de tipo A. EL hecho más destacable es que el periodo no tiene efecto sobre este riesgo debido a que la interacción entre tipo y periodo no está presente en el modelo.
\[RR_{period} = \frac{\lambda_{period+1,typeA}}{\lambda_{period,typeA}} = exp(\{-9.41 + 0.03*year + 0.02*(period+1)\} - \{-9.41 + 0.03*year + 0.02*period\})\] \[\text{de forma que } RR_{period} = exp(0.02) = 1.02\] El riesgo se mantiene constante cuando aumentamos en un año el periodo de operaciones. El riesgo asociado con aumentar dos años vendría dado por \(exp(2*0.02)\). Veamos el gráfico:
# Representamos dicho riesgo relativo
anyo <- seq(1,15,0.5) #incrementos de periodo desde 60 a 75
riesgo <- exp(anyo*0.024744)
datos <- data.frame(anyo,riesgo)
ggplot(datos,aes(x = anyo, y = riesgo)) +
geom_line() +
labs(x = "Periodo", y = "Riesgo Relativo", title ="Period para tipo A") +
theme_bw()
El riesgo aumenta cuando aumenta el periodo de servicio. Cuando este periodo se sitúa en una diferencia de 12 años el riesgo de sufrir una incidente es 1.35, es decir, un 33% más de riesgo en el barco más antiguo que en el más moderno.
Las herramientas de diagnóstico para este tipo d modelos son las mismas que el caso de los GLM con respuesta binaria. Los gráficos que vamos a utilizar son:
Usamos el modelo telas.fit
para el diagnóstico. Obtenemos todas las cantidades de interés del modelo. Para acelerar el proceso de diagnóstico utilizamos el comando plot(modelo)
que nos proporciona el gráfico de residuos versus ajustados, el gráfico qq de los residuos, el gráfico de linealidad (raíz cuadrada de la deviance residual vs valores predichos), y residuos vs variables predictoras. Obtenemos los estadísticos asociados con el modelo para valorar la existencia de valores influyentes.
telas.fit <-glm(breaks ~ wool*tension,family = poisson, glm_poi_01)
# Obtención de valores para el diagnóstico
fortify(telas.fit)
# Gráficos
par(mfrow=c(2,2))
plot(telas.fit)
No se aprecian ningún comportamiento digno de interés que pueda hacer dudar del modelo obtenido. Dado que tenemos dos factores sólo estimamos las medias correspondientes a las posibles combinaciones de ellos dos.
Utilizamos el modelo ajustado en la selección del modelo
barcos.fit <- glm(incidents ~ type + year +period + type:year,family = poisson, offset = log(service), glm_poi_07)# Obtención de valores para el diagnóstico
fortify(barcos.fit)
# Gráficos
par(mfrow=c(2,2))
plot(barcos.fit)
Se aprecia cierta tendencia en los residuos versus predichos que debería analizarse en más detalle. Realizamos el gráfico de las residuos con respecto a las variables numéricas para valorar la posible inclusión de otro tipo de efectos.
diagnostico <-fortify(barcos.fit)
# Residuos vs year
ggplot(diagnostico) +
geom_jitter(aes(year,.stdresid, color = type),) +
geom_smooth(aes(year,.stdresid, color = type), method=loess, se=FALSE) +
theme_bw()
# Residuos vs period
ggplot(diagnostico) +
geom_jitter(aes(period,.stdresid, color = type),) +
geom_smooth(aes(period,.stdresid, color = type), method=loess, se=FALSE) +
theme_bw()
No se aprecian tendencias destacables para period
pero si para year
. Proponemos un modelo de suavizado con respecto a esta variable y ajustamos un nuevo modelo. Para el ajuste de ese modelo utilizamos la función gam()
. Dado que tenemos pocos datos para tipo de barco, rebajamos el valor de \(k\) a 5 en la función de suavizado.
# Modelo con interacción type:period
M1 <- gam(incidents ~ type + period +
s(year, k = 5, m = 2, bs = "ps", by = type) +
type:period
,family = poisson, offset = log(service), glm_poi_07)
# Modelo sin interacción type:period
M2 <- gam(incidents ~ type + period +
s(year, k = 5, m = 2, bs = "ps", by = type)
,family = poisson, offset = log(service), glm_poi_07)
AIC(M1,M2)
El modelo sin interacción de type:period
tiene un menor valor de AIC y lo utilizamos como modelo final.
barcos.fit <- gam(incidents ~ type + period +
s(year, k = 5, m = 2, bs = "ps", by = type)
,family = poisson, offset = log(service), glm_poi_07)
# Resumen del modelo
summary(barcos.fit)
##
## Family: poisson
## Link function: log
##
## Formula:
## incidents ~ type + period + s(year, k = 5, m = 2, bs = "ps",
## by = type)
##
## Parametric coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -7.393678 0.606365 -12.193 < 2e-16 ***
## typeB -0.553323 0.255014 -2.170 0.03002 *
## typeC -0.696173 0.397851 -1.750 0.08015 .
## typeD -5.246512 7.967352 -0.659 0.51022
## typeE 0.870856 0.313020 2.782 0.00540 **
## period 0.025545 0.007951 3.213 0.00131 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df Chi.sq p-value
## s(year):typeA 1.166 1.306 0.771 0.52117
## s(year):typeB 1.973 2.226 22.167 2.43e-05 ***
## s(year):typeC 1.000 1.000 1.737 0.18758
## s(year):typeD 1.871 1.983 7.753 0.02457 *
## s(year):typeE 1.000 1.000 7.847 0.00509 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.971 Deviance explained = 86.7%
## UBRE = 0.33848 Scale est. = 1 n = 34
El modelo obtenido tiene buena capacidad explicativa. En cuanto a la interpretación de los coeficientes podemos ver que el riesgo de incidentes aumenta con el periodo y es mayor para los barcos de tipo E que para el resto. El tipo de barco con menor riesgo es el D. En cuanto a las funciones de suavizado, representamos sus efectos para observar el comportamiento del año para cada tipo de barco:
par(mfrow = c(2,3))
plot.gam(barcos.fit)
Se observan efectos casi lineales para todos los tipos salvo para los de tipo D. En este caso el riesgo de incidentes aumenta cuando lo hace año.
En cuanto al diagnóstico del modelo no se encuentra ningún comportamiento relevante (pvalores mayores que 0.05), salvo la existencia de un par de observaciones cuya predicción del predictor lineal está muy alejada del resto. Se podría intentar eliminar esas dos observaciones y ajustar un nuevo modelo, pero dado que el número de observaciones es bajo eso podría ocasionar que el modelo no se podría ajustar.
gam.check(barcos.fit)
##
## Method: UBRE Optimizer: outer newton
## full convergence after 10 iterations.
## Gradient range [-2.348054e-07,1.792604e-12]
## (score 0.3384798 & scale 1).
## Hessian positive definite, eigenvalue range [1.827615e-07,0.02021138].
## Model rank = 26 / 26
##
## Basis dimension (k) checking results. Low p-value (k-index<1) may
## indicate that k is too low, especially if edf is close to k'.
##
## k' edf k-index p-value
## s(year):typeA 4.00 1.17 1.17 0.82
## s(year):typeB 4.00 1.97 1.17 0.85
## s(year):typeC 4.00 1.00 1.17 0.85
## s(year):typeD 4.00 1.87 1.17 0.80
## s(year):typeE 4.00 1.00 1.17 0.81
El problema con las funciones de suavizado es que resulta más complicado la evaluación de los riesgos relativos. Al no disponer de una forma específica para las predictoras que forman parte del suavizado, no podemos obtener directamente dicho riesgo.
Para evaluar el riesgo del tipo de barco A con respecto al tipo E para un mismo valor de año y periodo utilizamos el código siguiente
# Para predecir
n <-20
year <- c(seq(60,75,length = n),seq(60,75,length = n))
period <- c(seq(60,75,length = n),seq(60,75,length = n))
type <- c(rep("A",n),rep("E",n))
newdata <- data.frame(year,period,type)
# Predicción
prediccion <- predict.gam(barcos.fit,newdata,type = "response",se.fit = FALSE)
# Riesgo
RR <- prediccion[(n+1):(2*n)]/prediccion[1:n]
datos <- data.frame(anyo = year[1:n], riesgo = RR)
ggplot(datos,aes(x = anyo, y = riesgo)) +
geom_line() +
labs(x = "Año", y = "Riesgo", title ="Tipo E vs tipo A") +
theme_bw()
El riesgo disminuye cuando aumenta el año de fabricación.
Vamos a construir la predicción para cada uno de los ejemplos que hemos venido trabajando a lo largo del tema.
Puesto que las dos predictoras son de tipo categórico solo se muestra la tabla de predicción con intervalo de confianza aproximado del 95%.
telas.fit <-glm(breaks ~ wool*tension,family = poisson, glm_poi_01)
grid <- glm_poi_01 %>%
data_grid(wool,tension)
# Obtenemos la predicción para el modelo ajusatdo
prediccion <- data.frame(grid, predict(telas.fit, grid, type = "response", se.fit=TRUE))
# Calculamos intervalos de confianza
prediccion <- prediccion %>% mutate(
lwr = fit - (1.96 * se.fit),
upr = fit + (1.96 * se.fit)
)
prediccion
El gráfico con las predicciones viene dado por:
# Creamos código de las combinaciones
newdata <- prediccion %>% mutate(grupo = paste(wool,tension))
# Representamos ordenando por varaible de interés
ggplot(newdata, aes(x = fct_reorder(grupo,fit), y= fit, color = wool)) +
geom_errorbar(aes(ymin=lwr, ymax=upr), width=.1) +
geom_line() +
geom_point() +
labs(x = "Wool - Tension", y = "Breaks") +
theme_bw()
Antes de proceder con la predicción para este ejemplo es necesario realizar la siguiente anotación. La inclusión de offset altera en cierta forma el proceso de predicción. En el caso de ajustar un glm
clásico la función predict(modelo.glm, type="response")
nos proporciona la predicción de la respuesta para ese modelo, pero no ocurre así cuando trabajamos con un gam
. En este caso la función predict(modelo.gam, type="response")
nos proporciona la predicción de la tasa de incidencia \(\lambda\) y no de la respuesta, por lo que es necesario multiplicar por el valor del offset para obtener la predicción de la respuesta. Si queremos predecir un valor en particular tendremos que asumir un valor para el offset con le objeto de calcular la predicción final de la respuesta.
En este caso tenemos un offset en la variable service
. Calculamos las predicciones para todo el banco de datos y verificamos cuanto se parecen a los valores reales observados.
# Modelo
barcos.fit <- gam(incidents ~ type + period +
s(year, k = 5, m = 2, bs = "ps", by = type)
,family = poisson, offset = log(service), glm_poi_07)
# Predicción sin offset
prediccion <- glm_poi_07 %>% mutate(fit = predict(barcos.fit,type = "response", se.fit=FALSE))
#prediccion
# Gráfico comparativo tasa real con tasa de predicción
ggplot(prediccion,aes(x = tasa,y = fit,color = type)) +
geom_point() +
geom_abline(intercept = 0, slope = 1) +
facet_grid(period ~ year) +
labs(x = "Tasas observadas" , y = "Tasas predichas", title = "Tasas en función de year (columnas) y period (filas)") +
theme_bw()
La predicción será buena cuando los datos se distribuyan a lo largo de la diagonal. Para el año de construcción 60 podemos ver que los datos no se colocan a lo largo de la diagonal. Esto es de esperar, dado que un supuesto natural es que cuando el barco es nuevo el riesgo de sufrir incidentes será bajo dado que sus horas de servicio no serán muy altas. Cuando relacionamos el año de fabricación y el de operación ya podemos ver que la predicción de la tasa obtenida se parece bastante a los datos reales observados, indicando un buen ajuste.
Copyright © 2018 Javier Morales. Universidad Miguel Hernández de Elche.