2012-09-12 18 views
9

Necesito obtener la media de una columna (aquí: puntaje) para filas específicas (aquí: años). En concreto, me gustaría saber la puntuación media de tres períodos:¿Cómo obtener la media de la columna solo para filas específicas?

  • período de 1: años < = 1,983
  • período de 2: años> = 1984 & años < = 1,990
  • período de 3: años> = 1991

Ésta es la estructura de mis datos:

country year  score   
Algeria 1980  -1.1201501 
Algeria 1981  -1.0526943 
Algeria 1982  -1.0561565 
Algeria 1983  -1.1274560 
Algeria 1984  -1.1353926 
Algeria 1985  -1.1734330 
Algeria 1986  -1.1327666 
Algeria 1987  -1.1263586 
Algeria 1988  -0.8529455 
Algeria 1989  -0.2930265 
Algeria 1990  -0.1564207 
Algeria 1991  -0.1526328 
Algeria 1992  -0.9757842 
Algeria 1993  -0.9714060 
Algeria 1994  -1.1422258 
Algeria 1995  -0.3675797 
... 

Los valores medios calculados deben agregarse al df en una columna adicional ("media"), es decir, el mismo valor medio para los años del período 1, para los del período 2, etc.

Así es como debería verse:

country year  score   mean 
Algeria 1980  -1.1201501  -1.089 
Algeria 1981  -1.0526943  -1.089 
Algeria 1982  -1.0561565  -1.089 
Algeria 1983  -1.1274560  -1.089 
Algeria 1984  -1.1353926  -0.839 
Algeria 1985  -1.1734330  -0.839 
Algeria 1986  -1.1327666  -0.839 
Algeria 1987  -1.1263586  -0.839 
Algeria 1988  -0.8529455  -0.839 
Algeria 1989  -0.2930265  -0.839 
Algeria 1990  -0.1564207  -0.839 
... 

Cada camino posible probé conseguido fácilmente súper complicado - y tengo que calcular las puntuaciones medias para diferentes períodos de tiempo durante más de 90 países ...

muchas muchas gracias por su ayuda!

Respuesta

14
datfrm$mean <- 
    with (datfrm, ave(score, findInterval(year, c(-Inf, 1984, 1991, Inf)), FUN= mean)) 

La pregunta del título es un poco diferente a la pregunta real y se respondería mediante el uso de indexación lógica. Si se quisiera solamente la media para un subconjunto particular year >= 1984 & year <= 1990 decir que se llevaría a cabo a través de:

mn84_90 <- with(datfrm, mean(score[year >= 1984 & year <= 1990])) 
+0

WOW! Esto fue sorprendentemente rápido, y muy útil. ¡Muchas gracias por esta solución súper elegante! – TiF

+4

La función 'findInterval' necesita una mejor agencia de publicidad. –

5

Desde findInterval requiere year que ser ordenados (como lo es en el ejemplo) estaría tentado a usar en cut caso no está ordenado [demostrado equivocado, gracias @DWin]. Para completar las data.table equivalentes (escalas de datos de gran tamaño) es:

require(data.table) 
DT = as.data.table(DF) # or just start with a data.table in the first place 

DT[, mean:=mean(score), by=cut(year,c(-Inf,1984,1991,Inf))] 

o findInterval es probablemente más rápido como se utiliza Dwin:

DT[, mean:=mean(score), by=findInterval(year,c(-Inf,1984,1991,Inf))] 
+2

Esa afirmación sobre findInterval es incorrecta (confirmada después de la prueba), pero gracias por la oferta de DT. –

+0

¡Gracias por probarlo! – TiF

+1

@DWin. Disculpas, confundí 'vec' y' x'. Tienes razón. –

Cuestiones relacionadas