2011-05-05 17 views
10

Estoy notando un comportamiento incoherente al aplicar la función median() a marcos de datos. "Comportamiento incoherente" generalmente significa que no entiendo algo, por lo que espero que alguien esté dispuesto a aclarar esto por mí.Comportamiento impar con mediana()?

I se dan cuenta de que algunas funciones (por ejemplo, min(), max()) convierten la trama de datos en un vector y devuelven el valor correspondiente para todo el df mientras mean() y sd() devuelven un valor para cada columna. Si bien es un poco confuso, esas diferencias en el comportamiento no causan muchos problemas ya que la mayoría del código se rompería si se devuelve un escalar en lugar de un vector. Sin embargo, median() parece ser inconsistente. Por ejemplo:

dat <- data.frame(x=1:100, y=2:101) 
median(dat) 

Devuelve un vector: [1] 50.5 51.5

Pero, a veces se rompe:

dat2 <- data.frame(x=1:100, y=rnorm(100)) 
median(dat2) 

Devuelve: [1] NA NA Warning messages: 1: In mean.default(X[[1L]], ...) : argument is not numeric or logical: returning NA 2: In mean.default(X[[2L]], ...) : argument is not numeric or logical: returning NA

Sin embargo, median(dat2$x) y median(dat2$y) tanto el rendimiento como el resultado correcto.

también incluirá las siguientes:

dat3 <- data.frame(x=1:100, y=1:100) 
dat4 <- data.frame(x=1:100, y=100:199) 

En lo anterior, median(dat3) vuelve [1] 50.5 NA mientras median(dat4) devuelve [1] 50.5 149.5! Esperaría que ninguno de los dos funcionara. Entonces, claramente no entiendo cómo funciona la función median().

Además, funciones como sd, mean(), min() y max() todo ceden sus esperados (si aparentemente inconsistente) resultados en todos los casos anteriores.

Sé que puedo usar algo como sapply(dat2, median) para obtener el resultado necesario, pero me pregunto por qué los dioses R decidieron implementar estas funciones estadísticas básicas de una manera que, al menos en apariencia, parece inconsistente. Sospecho que yo, y probablemente otros neófitos, probablemente no estoy entendiendo algún concepto fundamental, y agradecería su visión.

+1

Ojalá hubiera leído R Inferno un poco más de cerca. Acabo de volver y mirar, y el autor dice: "El ejemplo de la mediana con marcos de datos es problemático ... no hay un método de marco de datos de la mediana. En este caso particular, obtiene la respuesta correcta, pero eso es un accidente. En otros casos, obtienes respuestas raras ". (p.54). Ahora estoy motivado para darle a R Inferno una lectura buena y sólida este fin de semana. –

Respuesta

12

Este fenómeno exacto se debatió recientemente en el subproceso median and data frames en R-devel. El consenso parece ser que el método mean.data.frame debe estar en desuso y los usuarios deben confiar en sapply.

+1

+1 para destacar el problema 'mean.data.frame'. – aL3xa

+2

Perfecto, gracias! Estoy un poco avergonzado por no haber encontrado ese hilo. Está claro que 'mean' y' sd' son las funciones inconsistentes, no 'median' (aunque todavía creo que es inconsistente de otras maneras). En retrospectiva, es extraño esperar una función que generalmente agregue un vector de números para trabajar en un marco de datos. Una mejor pregunta habría preguntado por qué mean.data.frame se implementó en primer lugar. –

5

median no tiene un método para objetos de clase data.frame, a diferencia de mean. Use el paquete plyr y la función colwise para lograr el resultado deseado. O use la familia de funciones *apply.

> sapply(mtcars, median)                          
    mpg  cyl disp  hp drat  wt qsec  vs  am gear            
19.200 6.000 196.300 123.000 3.695 3.325 17.710 0.000 0.000 4.000            
    carb                              
    2.000                              
> colwise(median)(mtcars)                          
    mpg cyl disp hp drat wt qsec vs am gear carb                  
1 19.2 6 196.3 123 3.695 3.325 17.71 0 0 4 2 
+0

Gracias aL3xa. Ha sido mi costumbre usar sapply. Todavía soy un poco nuevo para R y todavía me molesta que las funciones no especifiquen tipos de argumentos y arrojen un error si se les pasa algo inapropiado. Parece que el mejor hábito es usar siempre sapply o por aire cuando se desea un resultado columna por columna. –

+0

Puede usar familias '* apply', es una buena práctica. – aL3xa

1

La forma más fácil es con el paquete miscTools

> library(miscTools) 
> dat3 <- data.frame(x=-50:50, y=(-50:50)^2) 
> colMedians(dat3) 
    x y 
    0 625 

que es correcta, a diferencia de

> median(dat3) 
[1] 0 850 

El paquete matrixStats también tiene una función colMedians, pero no para tramas de datos.

+0

Gracias @Henry. No sabía sobre miscTools; parece que hay algunas buenas herramientas de álgebra lineal allí. –

Cuestiones relacionadas