Modelos Lineales Generalizados

Introducción




logo

Especialización en Estadística Aplicada

Roberto Trespalacios

Instalar paquetes

  1. Instalar la última versión de R (www.rproject.com) y RStudio (www.rstudio.com). Por ahora asegúrese de instalar las siguientes librerías de R:
# Librerias de R
# ggplot2 y lattice: graficas en paneles
# knitr: reportes el LaTeX y R
# dplyr: manipulacion de datos estadisticos por grupos, ordenamiento, etc
# haven: importa bases de datos de SAS, SPSS y Stata directamente a R
# readxl: Importa bases de datos de Excel a R
pckgs = c("ggplot2", "knitr", "lattice", "dplyr", "haven", "readxl")
install.packages(pckgs, repos="http://cran.us.r-project.org")

Para instalar las librerías que no estén instaladas únicamente

# ipak function: instalar y leer multiples linrarías de R.
# verifique si las librerias estan instaladas. Instalarlas si no estan, luego lea la libreria i
# Source: https://gist.github.com/stevenworthington/3178163
ipak <- function(pkg){
new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
  if(length(new.pkg)){install.packages(new.pkg, dependencies = TRUE)}
  sapply(pkg, require, character.only = TRUE)
}
packages <- c("ggplot2", "dplyr", "lattice", "nlmeU", "nlme","haven", "GGally")
ipak(packages)

Instalar paquetes que están en GitHub

Primero, necesita instalar el paquete devtools. Puedes hacer esto desde CRAN. Invoque R y luego escriba

install.packages("devtools")

Cargue el paquete devtools.

library(devtools)

En la mayoría de los casos, solo usa install_github("author/package"). Por ejemplo, para el paquete R/broman, que existe en github.com/kbroman/broman, escribirías

install_github("kbroman/broman")

1. Degeneración macular relacionada con la edad

  • Estudio clínico en varios centros comparando una droga experimental con un placebo, Galecki (2013)

  • Pacientes con Degeneración macular relacionada con la edad (ARMD: Age-Related Macular Degeneration)

  • Los pacientes que padecen de ARMD la pierden visión progresivamente. Se midió la agudeza visual de 240 pacientes al comienzo del estudio en cuatro ocasiones después de la aleatorización a los dos grupos (4, 12, 24 y 52 semanas).

  • La agudeza visual se mide de acuerdo a la habilidad de los pacientes para leer las líneas en imágenes estandarizadas. La variable de interés en el estudio corresponde al número de letras leídas correctamente.

Una muestra de los datos armd

library(nlmeU)
head(armd0)
  subject treat.f visual0 miss.pat   time.f time visual tp
1       1  Active      59     --XX Baseline    0     59  0
2       1  Active      59     --XX     4wks    4     55  1
3       1  Active      59     --XX    12wks   12     45  2
4       2  Active      65     ---- Baseline    0     65  0
5       2  Active      65     ----     4wks    4     70  1
6       2  Active      65     ----    12wks   12     65  2

La variable respuesta es \( \texttt{visual} \). La variable \( \texttt{miss.pat} \) contiene el patrón de datos faltantes donde la $\texttt{X} indica que hay un dato faltante. Por ejemplo, el código $\texttt{-XX}, significa que el paciente tiene únicamente la primera y segunda medición (las últimas dos son faltantes). La variable \( \texttt{tp} \) indica el número consecutivo de la medición donde 0 es la medición al comienzo del estudio (baseline).

Gráfico de espagueti para agudeza visual (datos armd)

library(ggplot2)
ggplot(armd0, aes(x = time, y = visual, group = subject, color = treat.f))+
geom_line(size=.2)+
theme(text=element_text(size = 26))+
facet_grid(. ~ treat.f)

 Agudeza visual (datos armd0)

Algunos estadísticos descriptivos

Vamos a calcular algunos estadísticos descriptivos por cada ocasión y tratamiento. Note que la agudeza media disminuye a través del tiempo al igual que el número de pacientes en el estudio.

# Media por tratamiento
means_vis <- aggregate(visual ~ treat.f + time, data=armd0, mean)
means_vis <- means_vis[order(means_vis$treat.f),]
means_vis
   treat.f time   visual
1  Placebo    0 55.33613
3  Placebo    4 53.96581
5  Placebo   12 52.87179
7  Placebo   24 49.33036
9  Placebo   52 44.43810
2   Active    0 54.57851
4   Active    4 50.91228
6   Active   12 48.67273
8   Active   24 45.46078
10  Active   52 39.10000

Diagrama de cajas

ggplot(armd0, aes(x=time.f, y=visual))+
geom_boxplot()+
theme(text=element_text(size = 26))+
facet_grid(. ~ treat.f)

\label{fig:fig2}ARMD Trial: Gráficos de box-plot para la agudeza visual por tratamiento y tiempo.

Comentarios del diagrama de cajas

  • Diagrama de cajas por tiempo y tratamiento, la tendencia promedio de la agudeza visual a través del tiempo en ambos grupos podría ser explicada usando un modelo lineal.

  • Además, la variabilidad parece ser constante a través del tiempo.

  • Un aspecto importante en el modelaje estadístico, y en general en el análisis de datos, consiste en analizar los patrones de datos faltantes en los datos.

Datos faltantes

veamos los datos faltantes por cada semana de estudio para cada grupo

miss.data <- armd0[,c(2,4)]
table(miss.data)
         miss.pat
treat.f   ---- ---X --X- --XX -XX- -XXX X--- X-XX XXXX
  Placebo  510   36    8    9    0    2    4    0    1
  Active   430   60    8   15    3   10    4    2    5

Gráfico de medias por grupo

ggplot(means_vis, aes(x = time, y = visual, group = treat.f, 
                      color = factor(treat.f)))+
geom_line() + geom_point() + ylim(0, 90)+
theme(text=element_text(size = 26))+
labs(title="Visión de pacientes",y="Agudeza visual")

Agudeza visual (datos armd0)

Correlación por semanas

library("PerformanceAnalytics")
my_data <- armd.wide[,4:8]
chart.Correlation(my_data, histogram = TRUE, pch = 19)

Correlación agudeza visual vs. tiempo(datos armd0)

2. Respuestas Favorables en clínicas

Este conjunto de datos corresponde a un experimento en 12 clínicas sobre número de pacientes que respondieron favorablemente a dos tratamientos. Cada clínica reclutó 14 pacientes a los cuáles se les dió un tratamiento. En cada clínica se registró el número de pacientes que respondieron favorablemente al respectivo tratamiento en cada medición.

library("readr")
compaq <- read_csv("~/Desktop/libro_glm/datos/compaq.csv")
head(compaq)
# A tibble: 6 x 7
     id hospital         status stage   agegr ses            year
  <int> <chr>             <int> <chr>   <chr> <chr>         <dbl>
1     1 Public hospital       1 Stage 3 50-59 Poor-middle 0.00274
2     2 Public hospital       1 Stage 3 60+   High-middle 0.00821
3     3 Public hospital       1 Stage 3 50-59 Poor        0.0110 
4     4 Private hospital      1 Stage 4 <40   Poor-middle 0.0137 
5     5 Public hospital       1 Stage 4 40-49 Poor-middle 0.0192 
6     6 Public hospital       1 Stage 3 60+   High-middle 0.0219 

Conteo y razón del número de pacientes por etapa por tipo de hospital

library("dplyr")
compaq %>% group_by(hospital,stage) %>% summarize(razon=mean(status), n =n())
# A tibble: 8 x 4
# Groups:   hospital [?]
  hospital         stage   razon     n
  <chr>            <chr>   <dbl> <int>
1 Private hospital Stage 1 0.148   169
2 Private hospital Stage 2 0.325    77
3 Private hospital Stage 3 1.00      3
4 Private hospital Stage 4 0.441    34
5 Public hospital  Stage 1 0.249   361
6 Public hospital  Stage 2 0.435   313
7 Public hospital  Stage 3 0.923    78
8 Public hospital  Stage 4 0.862    29

Gráfico de medias por etapa par privado y público

library("ggplot2")
means <- compaq %>% group_by(hospital,stage) %>% summarize(razon=mean(status),n =n())

ggplot(means, aes(x = stage, y = razon, group = as.factor(hospital),color = factor(hospital))) +
  geom_line() + 
  theme(text=element_text(size = 26))+
  geom_point()

\label{fig.compaq} Número de pacientes que respondieron favorablemente.

Observaciones

  • la variable respuesta son conteos sobre un número dado de pacientes por clínica. Por lo tanto, un modelo que asuma normalidad en la respuesta quizás no sea adecuado

Razones:

  • la naturaleza de la variable es discreta

  • la media de la variable es siempre positiva, una restricción que no está presente en el modelo normal. En este caso, debemos pensar en modelar la respuesta usando una distribución tal como la Poisson o binomial negativa.

  • Promedio del número de pacientes que respondieron favorablemente tiende a aumentar en ambos grupos, pero en el grupo 1 (hospital privado), se nota un aumento mayor.

  • Una particularidad de estos datos es que la variable respuesta son conteos sobre un número dado de pacientes por clínica.

3. Circunferencia del tronco en árboles de naranja

Este conjunto de datos corresponde a un experimento para medir el crecimiento de árboles de naranja de acuerdo a la circunferencia del tronco.

\[ f(t)= \frac{\beta_0}{1+\varepsilon^{-(t-\beta_1)/\beta_2}}+\varepsilon \]

donde los

  • \( \beta's \) son parámetros desconocidos
  • \( \varepsilon \) es el error aleatorio
  • \( f(t) \) es el diámetro en el tiempo \( t \)

Al igual que en los casos anteriores, las respuestas a través del tiempo seguramente exhiben correlación entre sí.

Muestra de los datos Orange

library("readr")
orange <- read_csv("~/Desktop/libro_glm/datos/orange.csv")
head(orange)
# A tibble: 6 x 3
   Tree   age circumference
  <int> <int>         <int>
1     1   118            30
2     1   484            58
3     1   664            87
4     1  1004           115
5     1  1231           120
6     1  1372           142

Tendencia del crecimiento del tronco de los árboles

ggplot(orange, aes(x = age, y = circumference, group = as.factor(Tree),color = as.factor(Tree))) +
geom_line() +
theme(text=element_text(size = 26))+
geom_point()

\label{fig:fig5} Diametro de árboles de naranja (datos orange)

4. Nutrición

Este último conjunto de datos (retinol, datos de Nierenberg (1989) se desea estimar la relación entre el consumo diario de calorías y fibra en 315 pacientes.

Para este conjunto de datos un modelo lineal parece adecuado pero la varianza constante en los residuales (homocedasticidad) quizás no sea conveniente.

Note que la dispersión de las calorías tiende a aumentar a medida que la fibra aumenta, lo cual podría ser señal de heterocedasticidad en los errores. Una de las consecuencias de ajustar un modelo con varianza constante es que los errores estandar se podrían sobreestimar, y por lo tanto, la probabilidad de tener falsos negativos aumenta.

Muestra de datos retinol

# Descargando los datos retinol

retinol <- read_csv("~/Desktop/libro_glm/datos/retinol.csv")
# Renombrando las variables de los datos retinol
names(retinol) <- c("age", "sex", "smokstat", "quetelet", "vituse", "calories", 
                    "fat", "fiber", "alcohol","cholesterol", "betadiet", "retdiet", "betaplasma", "retplasma")

# Observemos una muestra de los datos
head(retinol)
# A tibble: 6 x 14
    age   sex smokstat quetelet vituse calories   fat fiber alcohol
  <int> <int>    <int>    <dbl>  <int>    <dbl> <dbl> <dbl>   <int>
1    64     2        2     21.5      1     1299  57.0  6.30       0
2    76     2        1     23.9      1     1032  50.1 15.8        0
3    38     2        2     20.0      2     2372  83.6 19.1       14
4    40     2        2     25.1      3     2450  97.5 26.5        1
5    72     2        1     21.0      1     1952  82.6 16.2        0
6    40     2        2     27.5      3     1367  56.0  9.60       1
# ... with 5 more variables: cholesterol <dbl>, betadiet <int>,
#   retdiet <int>, betaplasma <int>, retplasma <int>

Gráfico de consumo de calorias vs fibra (datos retinol)

ggplot(retinol, aes(x=fiber, y=calories, color=factor(sex))) +
theme(text=element_text(size = 26))+
geom_point()

\label{fig:fig6} Consumo de calorias vs fibra (datos retinol)

Boxplot variable calorias (datos retinol)

d=data.frame(
  h=factor(1), 
  ol=which(retinol$calories==max(retinol$calories)),
  rt=max(retinol$calories))
  • Se puede intentar una transformación de la variable respuesta
  • usando, por ejemplo, el logaritmo natural,
  • luego ajustar la regresión en la escala transformada.
  • A pesar de que esta es una práctica aceptada por la mayoría de estadísticos la interpretación del modelo en la escala original no es inmediata.
# Figura 1.7
ggplot(data=retinol,aes(x=factor(sex),y=calories))+
geom_boxplot()+
scale_x_discrete(labels= c("H", "M"))+
geom_text(data = d,aes(x=h,label = ol, y =rt-200), color= "red", size=6)+
theme(text=element_text(size = 26))+
labs(x="Sexo",y="Calorias")

\label{fig:fig7} Boxplot variable calorias (datos retinol))

Residuales del modelo lineal (datos retinol)

mod = lm(calories ~ fiber, data=retinol)
residuales<-data.frame(
  fitted=retinol$cholesterol[retinol$calories<5000],
  stdresid=resid(mod)[retinol$calories<5000])

Más adelante discutiremos como ajustar un modelo lineal con varianza no constante (errores heterocedásticos).

ggplot(data = residuales, aes(x=fitted,y=stdresid))+
  geom_point()+
  geom_hline(yintercept=0)+
  theme(text=element_text(size = 30))

 Residuales del modelo lineal consumo de calorias vs fibra (datos retinol).