Recorriendo t.tests para subconjuntos de marcos de datos en r
loops subset (3)
Tengo un marco de datos ''math.numeric'' con 32 variables. Cada fila representa un alumno y cada variable es un atributo. Los estudiantes se han colocado en 5 grupos según su calificación final.
Los datos tienen el siguiente aspecto:
head(math.numeric)
school sex age address famsize Pstatus Medu Fedu Mjob Fjob reason ... group
1 1 18 2 1 1 4 4 1 5 1 2
1 1 17 2 1 2 1 1 1 3 1 2
1 1 15 2 2 2 1 1 1 3 3 3
1 1 15 2 1 2 4 2 2 4 2 4
1 1 16 2 1 2 3 3 3 3 2 3
1 2 16 2 2 2 4 3 4 3 4 4
Estoy realizando pruebas t en cada variable para el grupo 1 frente a todos los otros grupos para identificar atributos significativamente diferentes con este grupo. Estoy buscando extraer los valores p para cada prueba, tales como:
t.test(subset(math.numeric$school, math.numeric$group == 1),
subset(math.numeric$school, math.numeric$group != 1))$p.value
t.test(subset(math.numeric$sex, math.numeric$group == 1),
subset(math.numeric$sex, math.numeric$group != 1))$p.value
t.test(subset(math.numeric$age, math.numeric$group == 1),
subset(math.numeric$age, math.numeric$group != 1))$p.value
He estado tratando de descubrir cómo puedo crear un bucle para hacer esto en lugar de escribir cada prueba de una en una. He intentado un bucle for, y lapply, pero hasta ahora no he tenido suerte.
Soy bastante nuevo en esto, por lo que cualquier ayuda sería apreciada.
Courtney
¿Cómo es esto?
pvals <- numeric() #the vector of p values
k <- 1 #in case you choose to use a subset not continuing from 1
# "for(i in seq(1,5))" is just doing the pvalues for the first 5 columns. You could do a
# list, like "c(1,2,4)" (in place of "seq(1,5)"), to do tests for columns 1, 2, and 4.
# To do all of the columns, try "for(i in seq(1,(ncol(math.numeric)-1)))".
for(i in seq(1,5)){
# using your code to grab the p-values and store them in the kth element of "pvals"
pvals[k] <- t.test(subset(math.numeric[,i], math.numeric$group == 1),
subset(math.numeric[,i], math.numeric$group != 1))$p.value
#iterating the "pvals" vector entry counter
k=k+1
}
pvals #printing the p values for each test
Considere dividir el marco de datos por grupo y usar
mapply()
en las columnas.
La salida se convierte en una lista compilada de estadísticas de pruebas: estadística, parámetro, valor p, confid.
intervalo, etc.
# FILTER ROWS AND SUBSET NUMERIC COLS
group1df <- df[df$group==1, 1:ncol(df)-1]
othgroupdf <- df[df$group!=1, 1:ncol(df)-1]
# T-TEST FCT
tfct <- function(v1, v2){
t.test(v1, v2)
}
# RUN T-TESTS BY COL, SAVE RESULTS TO LIST
ttests <- mapply(tfct, group1df, othgroupdf)
Sus datos de ejemplo no son suficientes para llevar a cabo pruebas t en todos los subgrupos.
Por esa razón, tomo el conjunto de datos de
iris
, que contiene 3 especies de plantas: Setosa, Versicolor y Virginica.
Estos son mis grupos.
Tendrá que ajustar su código en consecuencia.
A continuación, muestro cómo evaluar un grupo versus todos los demás grupos, un grupo versus otro grupo y todas las combinaciones de grupos individuales.
Un grupo versus todos los otros grupos combinados:
Primero, digamos que quiero comparar Versicolor y Virginica con Setosa, es decir, Setosa es mi
group 1
con el que se deben comparar todos los demás grupos.
Una manera fácil de lograr lo que quieres es lo siguiente:
sapply(names(iris)[-ncol(iris)], function(x){
t.test(iris[iris$Species=="setosa", x],
iris[iris$Species!="setosa", x])$p.value
})
Sepal.Length Sepal.Width Petal.Length Petal.Width
7.709331e-32 1.035396e-13 1.746188e-69 1.347804e-60
Aquí, he proporcionado los nombres de las diferentes variables en los
names(iris)
del conjunto de datos
names(iris)
, excluyendo la columna que indica la variable de agrupación
[-ncol(iris)]
(ya que es la última columna), como vector para
sapply
, que pasa el nombres correspondientes como argumentos de la función que he definido.
Un grupo versus cada uno de los otros grupos:
En caso de que quiera hacer comparaciones grupales para todos los grupos, lo siguiente puede ser útil: Primero, cree un marco de datos de todas las combinaciones de variables de grupo x que vaya a hacer, excluyendo la variable de agrupación en sí y el grupo de referencia, por supuesto. Esto se puede lograr mediante:
comps <- expand.grid(unique(iris$Species)[-1], # excluding Setosa as reference group
names(iris)[-ncol(iris)] # excluding group column
)
head(comps)
Var1 Var2
1 versicolor Sepal.Length
2 virginica Sepal.Length
3 versicolor Sepal.Width
4 virginica Sepal.Width
5 versicolor Petal.Length
6 virginica Petal.Length
Aquí,
Var1
son las diferentes especies, y
Var2
las diferentes variables para las cuales se deben hacer comparaciones.
El
group 1
referencia
group 1
o Setosa está implícito en este caso.
Ahora, puedo usar
apply
para crear las pruebas.
Hago esto usando cada fila de
comps
como argumento con dos elementos, el primero de los cuales indica qué turno de grupo es, y el segundo argumento indica qué variable debe compararse.
Estos se utilizarán para subconjugar el marco de datos original.
comps$pval <- apply(comps, 1, function(x) {
t.test(iris[iris$Species=="setosa", x[2]], iris[iris$Species==x[1], x[2]])$p.value
} )
donde el grupo 1, también conocido como Setosa, está codificado en la función. Esto me da un marco de datos con valores p para todas las combinaciones (con Setosa como grupo de referencia) para que sean fáciles de buscar:
head(comps)
Var1 Var2 pval
1 versicolor Sepal.Length 3.746743e-17
2 virginica Sepal.Length 3.966867e-25
3 versicolor Sepal.Width 2.484228e-15
4 virginica Sepal.Width 4.570771e-09
5 versicolor Petal.Length 9.934433e-46
6 virginica Petal.Length 9.269628e-50
Todas las combinaciones de grupos:
Puede expandir lo anterior fácilmente para producir un marco de datos que contenga valores p de pruebas t para cada combinación de grupos. Un enfoque sería:
comps <- expand.grid(unique(iris$Species), unique(iris$Species), names(iris)[-ncol(iris)])
Esto ahora tiene tres columnas. Los dos primeros son los grupos y el tercero la variable:
head(comps)
Var1 Var2 Var3
1 setosa setosa Sepal.Length
2 versicolor setosa Sepal.Length
3 virginica setosa Sepal.Length
4 setosa versicolor Sepal.Length
5 versicolor versicolor Sepal.Length
6 virginica versicolor Sepal.Length
Puede usar esto para llevar a cabo las pruebas:
comps$pval <- apply(comps, 1, function(x) {
t.test(iris[iris$Species==x[1], x[3]], iris[iris$Species==x[2], x[3]])$p.value
} )
Recibo un mensaje de error: ¿qué debo hacer?
t.test
puede arrojar un mensaje de error si el tamaño de la muestra es demasiado pequeño o si los valores son constantes para un grupo.
Esto es problemático ya que solo puede ocurrir para grupos específicos, y es posible que no sepa de antemano cuál es.
Sin embargo, el error interrumpirá toda la llamada a la función para
apply
, y no podrá ver ningún resultado.
Una forma de evitar esto e identificar los grupos problemáticos es ajustar la función
t.test
alrededor de
dplyr::failwith
(ver también
?tryCatch
).
Para mostrar cómo funciona esto, considere lo siguiente:
smalln <- data.frame(a=1, b=2)
t.test(smalln$a, smalln$b)
> Error in t.test.default(smalln$a, smalln$b) : not enough ''x'' observations
failproof.t <- failwith(default="Some default of your liking", t.test, quiet = T)
failproof.t(smalln$a, smalln$b)
[1] "Some default of your liking"
De esa manera, cada vez que
t.test
arroja un error, obtienes un carácter como resultado y el cálculo continúa con otros grupos.
No hace falta decir que también puede establecer el
default
en un número, o cualquier otra cosa.
No tiene que ser un personaje.
Descargo de responsabilidad estadístico: Habiendo dicho todo esto, tenga en cuenta que realizar varias pruebas t no es necesariamente una buena práctica estadística. Es posible que desee ajustar sus valores p para tener en cuenta las pruebas múltiples, o puede usar procedimientos de prueba alternativos que realicen pruebas conjuntas.