2011-03-30 8 views
5

tengo un dato de la siguiente manera:un promedio de más bloques continuos

f x 
A 1.1 
A 2.2 
A 3.3 
B 3.5 
B 3.7 
B 3.9 
B 4.1 
B 4.5 
A 5.1 
A 5.2 
C 5.4 
C 5.5 
C 6.1 
B 6.2 
B 6.3 

me gustaría hacer un promedio x sobre bloques continuos de f, para conseguir esto, similar a tapply(...,mean), pero consciente del hecho de que shouldn' t bloques mezcla separado y en el orden original:

f x 
A 2.2 
B 3.94 
A 5.15 
C 5.67 
B 6.25 

Respuesta

5

rle es una posibilidad:

> id <- rle(as.character(Data$f)) 
> Means <-tapply(Data$x,rep(1:length(id$lengths),id$lengths),mean)  
> data.frame(Means,f=id$values) 
    Means f 
1 2.200000 A 
2 3.940000 B 
3 5.150000 A 
4 5.666667 C 
5 6.250000 B 

Le da las ejecuciones y los valores, para que pueda usar ambos.

+0

+1 Grandes mentes otra vez eh @Joris ;-) –

+0

Sí, olvidé de ... Acc para la mayoría de los elegantes – mbq

6

He aquí una manera:

## reproducible code for example 
dat <- read.table(foo <- textConnection("f x 
A 1.1 
A 2.2 
A 3.3 
B 3.5 
B 3.7 
B 3.9 
B 4.1 
B 4.5 
A 5.1 
A 5.2 
C 5.4 
C 5.5 
C 6.1 
B 6.2 
B 6.3 
"), header = TRUE) 
close(foo) 

Utilizamos rle() para calcular las longitudes de ejecución de f y crear un nuevo factor fac que indexa los cambios, a falta de una palabra mejor, en f. A continuación, agregada sobre f y fac:

lens <- with(dat, rle(as.character(f))) 
dat$fac <- with(lens, factor(rep(seq_along(lengths), times = lengths))) 
aggregate(x ~ f + fac, data = dat, FUN = mean) 

El dar:

> aggregate(x ~ f + fac, data = dat, FUN = mean) 
    f fac  x 
1 A 1 2.200000 
2 B 2 3.940000 
3 A 3 5.150000 
4 C 4 5.666667 
5 B 5 6.250000 

Podemos caer fácilmente la segunda columna fac en el resultado si es indeseable:

> aggregate(x ~ f + fac, data = dat, FUN = mean)[,-2] 
    f  x 
1 A 2.200000 
2 B 3.940000 
3 A 5.150000 
4 C 5.666667 
5 B 6.250000 
+0

ah, ya veo ... ;-) Buen uso del agregado por cierto. –

+0

+1 para la primera mención 'rle' =) – mbq

Cuestiones relacionadas