[R-es] Media de elementos tomados uno a uno de un data.frame

Rubén Gómez Antolí lobo en mucharuina.com
Dom Nov 27 16:16:31 CET 2011


Hola:

Antes de nada, gracias por vuestras respuestas.

El 27/11/11 12:17, oscar.perpinan en upm.es escribió:
> Hola,
>
> Yo lo haría definiendo un data.frame en lugar de una matriz (como ya te
> han aconsejado),

Aclaro que mis datos estaban en un data.frame (como pone en el asunto 
del hilo) pero al preparar el ejemplo me fui a una matriz, vaya usted a 
saber porque.

Aprovecho para preguntar, ¿porque es mejor utilizar un data.frame en vez 
de una matriz? (En mi ignorancia, y hasta el momento en mi corta 
trayectoria por R, no he advertido demasiadas diferencias entre los dos 
tipos de objetos)

> definiendo una matriz para la estación y usando
> aggregate (como también te han aconsejado). Un posible código es:
>
> vientos <- data.frame(meses = c(rep(1, 5), rep(2, 5), rep(3, 5)), # Meses
> dir = rep(c("Calma", "Norte", "Este", "Sur", "Oeste"), 3), # Dirección
> calma = c(10, 0, 0, 0, 0, 8, 0, 0, 0, 0, 11, 0, 0, 0, 0), # Calma
> vel1 = c(0, 7, 8, 10, 1, 0, 9, 8, 7, 6, 0, 11, 10, 4, 3), # 1 - 5 m/s
> vel2 = c(0, 9, 10, 12, 7, 0, 10, 3, 2, 1, 0, 10, 7, 6, 8)) # 6 - 10 m/s
>
> est = function(x){
> n = (x - 1) %/% 3 + 1
> ests = c('inv', 'pri', 'ver', 'oto')
> res = ests[n]
> res
> }

Vale, entiendo que el objetivo de la función es «cambiar» el número de 
los meses por la estación a la que pertenecen. Lo que me pierde es la 
definición de «n», ¿restamos 1 para dividir por tres y sumar 1? No lo 
pillo, lo siento.

> aggregate(cbind(vel1, vel2) ~ est(meses) + dir, FUN = mean, data = vientos)

Con el ejemplo preparado esto funciona de escandalo, con los datos 
reales «medio funciona». Varias cosas:

- Con cbind agrupamos las columnas, en los datos reales tengo:

  > dim(Aero.vientos)
[1] 180  16

dieciséis columnas, que no son demasiadas, pero si hubiera muchas más, 
¿como podría «pasarlas» a cbind de una tacada?

(Bueno, poco a poco, acabo de pensar -cosa muy importante, pensar- y 
probar con as.matrix(Aero.vientos[,3:14]) y funciona aunque las columnas 
del resultado vienen señaladas con NA).

- Segundo problema: ejecutando

aggregate(
   cbind(as.matrix(Aero.vientos[,3:14])) ~
     est(Aero.vientos[["Meses"]]) + Aero.vientos[["Dirección"]],
   FUN = mean,
   data = Aero.vientos[,1:14]
)

El resultado no es el esperado.

   est(Aero.vientos[["Meses"]]) Aero.vientos[["Dirección"]]
1                          inv                       Total
2                          oto                       Total
3                          pri                       Total
4                          ver                       Total
   as.matrix(Aero.vientos[, 3:14])       NA       NA       NA       NA 
       NA
1                        11,53333 32,39833 33,41667 12,76000 7,166667 
1,8000000
2                        10,93333 34,11167 36,10000 12,15667 5,545000 
0,9866667
3                        13,20000 30,63050 30,52367 12,46711 9,733556 
2,8521667
4                        15,96667 33,95333 32,14667 10,29500 6,385000 
1,0766667

[...]

Solo agrupa por la dirección "Total" -que, precisamente, es una que 
quiero eliminar-, cuando hay unas cuantas más:

dimnames(Aero.vientos)[[2]]
  [1] "Meses"      "Dirección"  "Calma"      "X01...06"   "X06...11"
  [6] "X11...16"   "X16...21"   "X21...26"   "X26...31"   "X31...36"
[11] "X36...41"   "X41...46"   "X46...50"   "X..50"      "Total"
[16] "Nº.de.obs."

Hasta el momento no consigo encontrar solución. Consultando la ayuda de 
aggregate he probado varias cosas, como:

aggregate(
   cbind(Aero.vientos[,3],Aero.vientos[,4]) #~
     #est(Aero.vientos[["Meses"]]),
   ,list(Dir=Aero.vientos[["Dirección"]]),
   FUN = mean, data = Aero.vientos[,1:14]
)

(Si se incorpora la función est(), aggregate falla)

que realiza el agrupamiento por direcciones tal y como quiero pero 
obvia, logicamente a la vista del código, la agrupación por estaciones.

¡¡ Opss !! Bien, como voy pensando y probando mientras escribo, he 
atinado por prueba y error:

aggregate(
   cbind(as.matrix(Aero.vientos[,3:14])),
   list(Dir=Aero.vientos[["Dirección"]],
     Est=est(Aero.vientos[["Meses"]])),
   FUN = mean, data = Aero.vientos[,1:14]
)

Además, respeta el nombre de las columnas.

¿Alguien haría el favor de explicarme porque falla el primero y 
«acierta» el último?

> Para la mediana debes usar median y para la desv. estandar sd.

Pues el mismo código anterior falla miserablemente para estas dos 
funciones. :^(

 > aggregate(
+   cbind(as.matrix(Aero.vientos[,3:14])),
+   list(Dir=Aero.vientos[["Dirección"]],
+     Est=est(Aero.vientos[["Meses"]])),
+   FUN = sd, data = Aero.vientos[,1:14]
+ )
Error en FUN(X[[1L]], ...) :
   el argumento(s) no fue utilizado(s) (data = list(Meses = c(1, 1, 1, 
1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
6, 6, 6,
6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 
8, 8, 8,
8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 
10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
Calls: aggregate ... aggregate.data.frame -> lapply -> FUN -> lapply -> FUN

> En la
> ayuda de aggregate te cuentan como conseguir resultados de varias
> funciones a la vez.

Pues he repasado toda la ayuda y, la verdad, no he visto nada.

> Saludos.
>
> Oscar.
> --
> Enviado desde mi teléfono Android con K-9 Mail. Disculpa mi brevedad

Enviar el correo anterior desde el móvil es, cuando menos, una proeza; 
no hay nada que disculpar, al revés, es de ensalzar.

Muchas gracias de nuevo a todos, a ver si alguien me puede dar una pista 
para lo que me queda. (Y perdón por el ladrillo que ha quedado)

Salud y Revolución.

Lobo.

Pd: Por cierto Oscar (permíteme tutearte), terminando con esto me lío 
con datos de insolación, así que creo que me pelearé con tu paquete 
SolaR que tiene una pinta estupenda; si no pregunto es buena señal. ^_^
-- 
Libertad es poder elegir en cualquier momento. Ahora yo elijo GNU/Linux,
para no atar mis manos con las cadenas del soft propietario.
---------
Desde El Ejido, en Almería, usuario registrado Linux #294013
http://www.counter.li.org



Más información sobre la lista de distribución R-help-es