Análisis de muestreo de conglomerados con R

Vamos a presentar el uso del paquete de encuestas para R para hacer inferencias utilizando datos de encuestas recopilados mediante un diseño de muestreo por conglomerados. Demuestra varios problemas comunes como la estimación de las medias y los totales de la población en función de los datos recopilados utilizando diseños de muestreo por conglomerados de una etapa y dos etapas, muestreo de una o varias etapas donde las unidades de la primera etapa se muestrean con reemplazo con probabilidades proporcionales al tamaño (PPT), y muestreo por conglomerados donde las unidades de la primera etapa se muestrean utilizando un muestreo aleatorio estratificado.

Especificación de muestreo de conglomerados de una etapa

En un diseño estándar de muestreo por conglomerados de una etapa, los conglomerados de elementos se seleccionan utilizando un diseño de muestreo probabilístico y se observan todos los elementos en cada conglomerado seleccionado. Los datos que se utilizarán para la ilustración se encuentran en el marco de datos apiclus1 del paquete de la encuesta. La población son todas las escuelas del estado de California con al menos 100 estudiantes. Los clústeres son distritos escolares (dname o dnum) y los elementos son escuelas (sname o snum). Entonces n = 15 distritos seleccionados en apiclus1 fueron seleccionados mediante muestreo aleatorio simple, y apiclus1 incluye observaciones de todas las escuelas de la población que se encuentran en los distritos seleccionados. Los datos se pueden cargar en una sesión R usando los siguientes comandos. Extraemos la data apipop para el análisis, a continuación mostraremos algunas de las variables que vamos a necesitar en el estudio:

cds: Identificador único

dnum: Nombre del distrito

name: Nombre del colegio

snum: Número del colegio

library(survey)
## Warning: package 'survey' was built under R version 4.2.2
## Loading required package: grid
## Loading required package: Matrix
## Loading required package: survival
## 
## Attaching package: 'survey'
## The following object is masked from 'package:graphics':
## 
##     dotchart
library(Matrix)
library(survival)
data(api)
head(apipop)
##              cds stype            name                      sname snum
## 1 01611190130229     H    Alameda High               Alameda High    1
## 2 01611190132878     H    Encinal High               Encinal High    2
## 3 01611196000004     M  Chipman Middle             Chipman Middle    3
## 4 01611196090005     E Lum (Donald D.) Lum (Donald D.) Elementary    4
## 5 01611196090013     E Edison Elementa          Edison Elementary    5
## 6 01611196090021     E Otis (Frank) El    Otis (Frank) Elementary    6
##                  dname dnum   cname cnum flag pcttest api00 api99 target growth
## 1 Alameda City Unified    6 Alameda    1   NA      96   731   693      5     38
## 2 Alameda City Unified    6 Alameda    1   NA      99   622   589     11     33
## 3 Alameda City Unified    6 Alameda    1   NA      99   622   572     11     50
## 4 Alameda City Unified    6 Alameda    1   NA      99   774   732      3     42
## 5 Alameda City Unified    6 Alameda    1   NA      99   811   784      1     27
## 6 Alameda City Unified    6 Alameda    1   NA     100   780   725      4     55
##   sch.wide comp.imp both awards meals ell yr.rnd mobility acs.k3 acs.46
## 1      Yes      Yes  Yes    Yes    14  16   <NA>        9     NA     NA
## 2      Yes       No   No     No    20  18   <NA>       13     NA     NA
## 3      Yes      Yes  Yes    Yes    55  25   <NA>       20     NA     26
## 4      Yes      Yes  Yes    Yes    35  26   <NA>       21     20     30
## 5      Yes      Yes  Yes    Yes    15   9   <NA>       11     20     29
## 6      Yes      Yes  Yes    Yes    25  18   <NA>       12     20     29
##   acs.core pct.resp not.hsg hsg some.col col.grad grad.sch avg.ed full emer
## 1       25       91       6  16       22       38       18   3.45   85   16
## 2       27       84      11  20       29       31        9   3.06   90   10
## 3       27       86      11  31       30       20        8   2.82   80   12
## 4       NA       96       3  22       29       31       15   3.32   96    4
## 5       NA       96       3   9       29       26       33   3.76   95    5
## 6       NA       87       6  11       28       41       13   3.44   90    5
##   enroll api.stu
## 1   1278    1090
## 2   1113     840
## 3    546     472
## 4    330     272
## 5    233     216
## 6    276     247

El comando data(api) en realidad carga varios marcos de datos que son muestras del marco de datos apipop.

Un diseño de muestreo por conglomerados de una etapa se especifica de manera similar a un diseño de muestreo aleatorio simple, excepto que el argumento id debe especificarse usando una variable que identifica de manera única cada conglomerado, y el argumento fpc es el número de conglomerados en lugar del número de elementos en el población.

El código está creando un objeto de diseño de encuesta compleja en dos etapas utilizando la función svydesign del paquete “survey” en R. El objeto de diseño se almacena en la variable api.twostage.

El diseño de dos etapas se utiliza cuando la población está organizada en grupos más grandes (por ejemplo, distritos escolares) y se selecciona una muestra aleatoria de estos grupos (primera etapa). Luego, se selecciona una muestra aleatoria de los elementos dentro de los grupos seleccionados (segunda etapa). En este caso, los grupos se identifican por la variable dnum y los elementos dentro de los grupos se identifican por la variable snum.

El objeto de diseño incluye información sobre el tamaño de la población, el tamaño de la muestra, el efecto del diseño, el cálculo de los errores estándar y los coeficientes de varianza, entre otros aspectos.

La función summary se utiliza para obtener un resumen de las características del objeto de diseño, incluyendo información sobre el número de unidades primarias de muestreo, el número de unidades secundarias de muestreo, los pesos de muestreo, el efecto del diseño y el tamaño de la muestra.

api.onestage <- svydesign(id = ~dnum, data = apiclus1, fpc = ~fpc)
summary(api.onestage)
## 1 - level Cluster Sampling design
## With (15) clusters.
## svydesign(id = ~dnum, data = apiclus1, fpc = ~fpc)
## Probabilities:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.01982 0.01982 0.01982 0.01982 0.01982 0.01982 
## Population size (PSUs): 757 
## Data variables:
##  [1] "cds"      "stype"    "name"     "sname"    "snum"     "dname"   
##  [7] "dnum"     "cname"    "cnum"     "flag"     "pcttest"  "api00"   
## [13] "api99"    "target"   "growth"   "sch.wide" "comp.imp" "both"    
## [19] "awards"   "meals"    "ell"      "yr.rnd"   "mobility" "acs.k3"  
## [25] "acs.46"   "acs.core" "pct.resp" "not.hsg"  "hsg"      "some.col"
## [31] "col.grad" "grad.sch" "avg.ed"   "full"     "emer"     "enroll"  
## [37] "api.stu"  "fpc"      "pw"

Interpretación:

Esta salida de datos corresponde a la descripción del diseño de muestreo por conglomerados de un solo nivel (1-level Cluster Sampling) y algunos detalles sobre los datos de la muestra. Aquí está la explicación de cada línea:

“Data variables: [...]”: Esta es una lista de las variables en el conjunto de datos. Hay 39 variables que incluyen información sobre la identificación de las escuelas y distritos, características de los estudiantes y escuelas, y factores de ponderación para ajustar el diseño de muestreo.

Two-Stage Cluster Sampling Specification


Una especificación típica de un diseño de muestreo por conglomerados en dos etapas requiere variables para identificar las unidades de muestreo primarias y secundarias, así como el número total de conglomerados en la población (N) y el número total de elementos en cada grupo seleccionado (Mi). El marco de datos apiclus2 es una muestra obtenida mediante un diseño de muestreo por conglomerados en dos etapas utilizando una muestra aleatoria simple de n = 40 distritos, donde dentro del distrito seleccionado i

uno o más de los Mi.

Las escuelas del distrito fueron seleccionadas mediante un muestreo aleatorio simple. Este diseño de muestreo por conglomerados en dos etapas se puede especificar de la siguiente manera.

El código api.twostage <- svydesign(id = ~dnum + snum, data = apiclus2, fpc = ~fpc1 + fpc2) está creando un objeto de diseño de muestreo para un análisis de encuesta en R utilizando la librería “survey”. Este objeto se utiliza para realizar análisis estadísticos tomando en cuenta el diseño complejo de la encuesta, como estratificación, conglomeración, y/o ponderación.

Específicamente, este código está creando un objeto de diseño de muestreo de dos niveles (twostage) para una encuesta (apiclus2) con un diseño estratificado por la variable dnum y conglomerado por la variable snum. La encuesta se ha llevado a cabo utilizando un diseño de muestreo de dos etapas, donde la primera etapa es la selección de los conglomerados y la segunda etapa es la selección de las unidades dentro de los conglomerados seleccionados. Este diseño de muestreo se utiliza comúnmente en encuestas que involucran poblaciones grandes y dispersas geográficamente.

En este caso, el objeto de diseño utiliza las variables de factores de corrección de ponderación fpc1 y fpc2, que corresponden a factores de corrección de ponderación específicos para cada nivel del diseño de muestreo.

api.twostage <- svydesign(id = ~dnum + snum, data = apiclus2, fpc = ~fpc1 + 
    fpc2)
summary(api.twostage)
## 2 - level Cluster Sampling design
## With (40, 126) clusters.
## svydesign(id = ~dnum + snum, data = apiclus2, fpc = ~fpc1 + fpc2)
## Probabilities:
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.003669 0.037743 0.052840 0.042390 0.052840 0.052840 
## Population size (PSUs): 757 
## Data variables:
##  [1] "cds"      "stype"    "name"     "sname"    "snum"     "dname"   
##  [7] "dnum"     "cname"    "cnum"     "flag"     "pcttest"  "api00"   
## [13] "api99"    "target"   "growth"   "sch.wide" "comp.imp" "both"    
## [19] "awards"   "meals"    "ell"      "yr.rnd"   "mobility" "acs.k3"  
## [25] "acs.46"   "acs.core" "pct.resp" "not.hsg"  "hsg"      "some.col"
## [31] "col.grad" "grad.sch" "avg.ed"   "full"     "emer"     "enroll"  
## [37] "api.stu"  "pw"       "fpc1"     "fpc2"

Interpretación:

#######

El código unique(weights(api.onestage)) está devolviendo los valores únicos de las ponderaciones finales de la encuesta asociada al objeto de diseño de muestreo api.onestage.

La función weights() se utiliza para extraer las ponderaciones finales de la encuesta asociada al objeto de diseño de muestreo. En este caso, al aplicar la función weights() al objeto de diseño api.onestage, se obtiene un vector con todas las ponderaciones finales de las unidades muestrales de la encuesta. Luego, la función unique() se utiliza para devolver solo los valores únicos de este vector.

Las ponderaciones finales son valores que se asignan a cada unidad muestral de la encuesta para ajustar por el diseño de muestreo y lograr representatividad de la población objetivo.

unique(weights(api.onestage))
## [1] 50.46667

Interpretación Esta salida muestra los resultados de la función summary() aplicada a un objeto de diseño de muestreo generado con svydesign() en R.

Las primeras líneas muestran las probabilidades de inclusión de las unidades primarias de muestreo (UPM) y la población total de UPM en la muestra. La probabilidad de inclusión se refiere a la probabilidad de que una UPM determinada se seleccione en la muestra. Los valores mínimos, máximo, media, y los cuartiles de las probabilidades de inclusión se proporcionan en la salida.

Las siguientes líneas muestran las variables incluidas en el conjunto de datos de apiclus2. En este caso, hay 40 unidades de muestreo primarias (dnum) y 126 unidades de muestreo secundarias (snum). También se incluyen los valores de los factores de corrección por conglomerado (fpc1 y fpc2) para ajustar los pesos de muestreo.

Estimación de Medias y Totales

Los pesos de muestreo implícitos en un diseño dado son los recíprocos de las probabilidades de inclusión, de modo que wij=1/πij, donde πij es la probabilidad de incluir el j-ésimo elemento dentro del i -ésimo conglomerado en la muestra. Para el muestreo por conglomerados de una etapa, si los conglomerados se muestrean utilizando un muestreo aleatorio simple, entonces wij=N/n ya que πij=n/N es la probabilidad de inclusión del j-ésimo elemento en el i -ésimo grupo. Para el ejemplo anterior, n=15 y N=757,

unique(weights(api.onestage))
## [1] 50.46667

Entonces wij=757/15≈50.47. Esto se puede verificar usando la función de pesos.

###############################################

El código svymean(~enroll, design = api.onestage) calcula la media de una variable llamada “enroll” en la población objetivo de la encuesta, utilizando el objeto de diseño de muestreo api.onestage en R, que ha sido creado utilizando la librería “survey”.

La función svymean() se utiliza para estimar medias, totales, proporciones u otros estadísticos poblacionales a partir de datos de encuestas complejas que han sido muestreados utilizando un diseño de muestreo complejo. En este caso, se está calculando la media de la variable “enroll”, que se espera que represente la tasa de matriculación en una determinada población.

El argumento ~enroll especifica que la variable “enroll” es la variable de interés para calcular la media, mientras que el argumento design = api.onestage especifica el objeto de diseño de muestreo api.onestage que se ha creado anteriormente para realizar el cálculo de la media.

svymean(~enroll, design = api.onestage)
##          mean     SE
## enroll 549.72 45.191

Interpretación:

La salida indica que la media (promedio) de la variable “enroll” es de 549.72 estudiantes, y que el error estándar (SE) asociado a esta estimación es de 45.191. El error estándar es una medida de la variabilidad de la estimación de la media en diferentes muestras, y puede usarse para calcular intervalos de confianza alrededor de la estimación puntual.

El código svymean(~enroll, design = api.twostage, na.rm = TRUE) calcula la media y el error estándar de la variable enroll en una muestra obtenida a través de un diseño de muestreo complejo de dos niveles utilizando la función svymean del paquete survey en R.

Específicamente, la fórmula ~enroll especifica que se debe calcular la media de la variable enroll. El argumento design especifica el diseño de muestreo complejo utilizado, en este caso el diseño de dos niveles definido en el objeto api.twostage. El argumento na.rm se establece en TRUE para indicar que se deben omitir los valores faltantes al calcular la media.

svymean(~enroll, design = api.twostage, na.rm = TRUE)
##          mean     SE
## enroll 526.26 80.341

Las escuelas con valores perdidos se pueden identificar fácilmente.

with(apiclus2, sname[is.na(enroll)])
## [1] "Virginia Avenue Elementary"    "Fairfax Elementary"           
## [3] "California City Middle"        "Mojave Elementary"            
## [5] "Joshua Middle"                 "Ulrich (Robert P.) Elementary"

El código svytotal(~enroll, design = api.onestage) calcula la suma ponderada de la variable enroll utilizando un diseño de muestreo de un solo nivel (onestage) generado previamente por la función svydesign() del paquete survey. La suma ponderada se calcula tomando en cuenta los factores de expansión y la estructura de muestreo del diseño, por lo que representa una estimación del total poblacional de la variable enroll en la población objetivo.

svytotal(~enroll, design = api.onestage)
##          total      SE
## enroll 5076846 1389984

Interpretación

Se estima que la matrícula total de estudiantes en la población es de 5,076,846 unidades.

El error estándar de la estimación de la matrícula total de estudiantes es de 1,389,984 unidades.

El código primero calcula la media del número de matrículas (enroll) en la muestra usando el diseño de muestreo api.onestage, y almacena el resultado en el objeto tmp. Luego, el código multiplica el resultado de la media por el tamaño de la población de estudio (6194) para estimar el total de matrículas en la población.

tmp <- svymean(~enroll, design = api.onestage)
tmp[1] * 6194  # estimate
##  enroll 
## 3404940
SE(tmp) * 6194  # standard error
##          enroll
## enroll 279915.4
confint(tmp) * 6194  # confidence interval
##          2.5 %  97.5 %
## enroll 2856316 3953564

Sampling With Probabilities Proportional to Size (PPS)

for (i in unique(apiclus1$dnum)) {
    apiclus1$w[apiclus1$dnum == i] <- 6194/(15 * sum(apiclus1$dnum == i))
}
api.pps <- svydesign(id = ~dnum, data = apiclus1, weights = ~w)
svytotal(~enroll, design = api.pps)
##          total     SE
## enroll 2900735 233096
svymean(~enroll, design = api.pps)
##          mean     SE
## enroll 468.31 37.633

Muestreo por conglomerados estratificado

El marco de datos de maestros del paquete SDaA es una muestra de observaciones de maestros que utilizan un diseño de muestreo estratificado por conglomerados en dos etapas donde las unidades de muestreo primarias (escuelas) se seleccionaron mediante muestreo aleatorio estratificado, y las unidades de muestreo secundarias (maestros) se seleccionaron mediante muestreo aleatorio simple. El número de docentes en cada escuela seleccionada (Mi ) están en un marco de datos separado teachmi. Estos marcos de datos se pueden fusionar de la siguiente manera

library(SDaA)
## Warning: package 'SDaA' was built under R version 4.2.2
teacher.sample <- merge(teachers, teachmi, by = c("dist", "school"))

El marco de datos también carece de una variable para identificar a los maestros individuales, o los tamaños de estrato, pero estos pueden agregarse fácilmente al nuevo marco de datos.

Este código agrega dos nuevas variables a la tabla teacher.sample.

La variable teacher se crea como una secuencia numérica del 1 al número total de filas de la tabla teacher.sample.

La variable N se crea como una nueva variable con valores NA. Luego, se asigna el valor 66 a la variable N para las filas donde la variable dist es “sm/me”, y el valor 245 para las filas donde la variable dist es “large”.

teacher.sample$teacher <- 1:nrow(teacher.sample)
teacher.sample$N <- NA
teacher.sample$N[teacher.sample$dist == "sm/me"] <- 66
teacher.sample$N[teacher.sample$dist == "large"] <- 245

Ahora el diseño se puede especificar usando svydesign.

Específicamente, se utiliza la función svydesign() del paquete survey para crear el objeto teacher.design con los siguientes argumentos:

  • id = ~school + teacher: la variable de identificación del diseño es una combinación de las variables school y teacher. Esto indica que el muestreo se realizó en dos etapas: primero, se seleccionaron escuelas de cada estrato y luego, dentro de cada escuela seleccionada, se seleccionaron aleatoriamente algunos maestros.

  • data = teacher.sample: los datos de la encuesta se encuentran en el conjunto de datos teacher.sample.

  • strata = ~dist + NULL: la estratificación se realizó utilizando la variable dist. La segunda parte de la expresión (+ NULL) indica que no se utilizaron otras variables para la estratificación.

  • fpc = ~N + popteach: los factores de corrección del diseño se especifican utilizando la variable N (el tamaño de la escuela) y la variable auxiliar popteach (el número de maestros en cada escuela).

Luego, la función summary() se utiliza para imprimir un resumen del diseño, que incluye el número de estratos, PSUs, unidades de muestreo final, y la tasa de muestreo. Además, se proporciona información sobre los factores de corrección y los pesos de muestreo.

teacher.design <- svydesign(id = ~school + teacher, data = teacher.sample, strata = ~dist + 
    NULL, fpc = ~N + popteach)
summary(teacher.design)
## Stratified 2 - level Cluster Sampling design
## With (31, 310) clusters.
## svydesign(id = ~school + teacher, data = teacher.sample, strata = ~dist + 
##     NULL, fpc = ~N + popteach)
## Probabilities:
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.006259 0.031883 0.062585 0.056238 0.079435 0.093878 
## First-level Stratum Sizes: 
##            large sm/me
## obs          250    60
## design.PSU    23     8
## actual.PSU    23     8
## Population stratum sizes (PSUs): 
## large sm/me 
##   245    66 
## Data variables:
##  [1] "dist"     "school"   "hrwork"   "size"     "preprmin" "assist"  
##  [7] "popteach" "ssteach"  "teacher"  "N"

Tenga en cuenta que los argumentos de id, strata y fpc dan los valores apropiados para cada etapa de muestreo. Aquí la escuela y el maestro son las unidades de muestreo primaria y secundaria, respectivamente. Solo se estratificaron las unidades de muestreo primarias (es decir, escuelas), por lo que la variable de estratificación para las unidades de muestreo secundarias (es decir, maestros) se especifica como NULL (o podría omitirse por completo). Las variables N y popenseñar dan el número de escuelas en el estrato y el número de maestros en la escuela para un maestro dado en una escuela dada.

Estimaciones de τ y m, así como las estimaciones para cada estrato, se pueden obtener utilizando svytotal, svymean y svyby. Los estimadores son como los de los diseños de muestreo por conglomerados en dos etapas, pero las ponderaciones se calculan por separado para cada estrato.

options(survey.lonely.psu = "remove")
svytotal(~hrwork, design = teacher.design, na.rm = TRUE)
##         total    SE
## hrwork 260472 16613

###############################################

El código svymean(~hrwork, design = teacher.design, na.rm = TRUE) calcula la media de la variable hrwork en la muestra de la población representada por el objeto teacher.design, utilizando el método de estimación por diseño de muestreo complejo. La opción na.rm = TRUE indica que se deben excluir los valores faltantes (NA) en el cálculo de la media.

svymean(~hrwork, design = teacher.design, na.rm = TRUE)
##          mean    SE
## hrwork 34.094 0.626

#########################################################

El código svyby(~hrwork, by = ~dist, design = teacher.design, FUN = svytotal, na.rm = TRUE) calcula la suma total de horas trabajadas por los profesores agrupados por distrito (dist) en un diseño de muestreo complejo especificado por teacher.design utilizando la función svyby() del paquete survey. La función svyby() aplica una función de resumen específica (en este caso svytotal() que calcula la suma ponderada) a cada uno de los grupos definidos por la variable de agrupación (dist). El argumento na.rm = TRUE se utiliza para ignorar los valores faltantes en el cálculo.

svyby(~hrwork, by = ~dist, design = teacher.design, FUN = svytotal, na.rm = TRUE)
##        dist    hrwork        se
## large large 223228.60 15106.897
## sm/me sm/me  37243.51  6910.767

################################################################

El código svyby(~hrwork, by = ~dist, design = teacher.design, FUN = svytotal, na.rm = TRUE) realiza una operación de agregación por grupos en una muestra compleja estratificada.

La función svyby se utiliza para aplicar una función a variables en subgrupos de una muestra compleja. En este caso, hrwork es la variable que se está agregando y dist es la variable de agrupación. La opción design especifica el objeto de diseño de la encuesta, que describe la estructura de la muestra. La opción FUN especifica la función a aplicar a cada subgrupo y na.rm = TRUE indica que se deben excluir los valores faltantes de los cálculos.

En resumen, este código calcula la suma de horas trabajadas por los profesores en cada distrito escolar de la muestra compleja estratificada teacher.design.

svyby(~hrwork, by = ~dist, design = teacher.design, FUN = svytotal, na.rm = TRUE)
##        dist    hrwork        se
## large large 223228.60 15106.897
## sm/me sm/me  37243.51  6910.767

Tenga en cuenta que hay un par de complicaciones. Una es que hay algunos maestros en la muestra a los que les faltan valores para la variable objetivo hrwork (número informado de horas trabajadas por semana). Suponiendo que estos faltan al azar, esto se puede solucionar usando la opción na.rm = TRUE. El otro problema es que una de las unidades primarias de muestreo incluye una sola unidad secundaria de muestreo.

###########################################

El código with(teacher.sample, table(school)) cuenta la frecuencia de cada valor de la variable school en el objeto de datos teacher.sample. En otras palabras, el resultado es una tabla que muestra cuántas veces aparece cada valor único de la variable school.

with(teacher.sample, table(school))
## school
##  1  2  3  4  6  7  8  9 11 12 13 15 16 18 19 20 21 22 23 24 25 28 29 30 31 32 
##  1  4  7  7 11  4  5 21 10 13  3 24 24  2  3  8  7 13 16  9  8 18  8 22 18 16 
## 33 34 36 38 41 
##  5  7  4 10  2