2012-09-12 10 views
9

Potrzebuję uzyskać średnią z jednej kolumny (tutaj: wynik) dla konkretnych wierszy (tutaj: lata). W szczególności chciałbym wiedzieć, średni wynik dla trzech okresów:Jak uzyskać średnią kolumnę tylko dla określonych wierszy?

  • okresu 1: rok < = 1983
  • okres 2: lata> = 1984 & roku < = 1990
  • okres 3: rok> = 1991

jest to struktura moich danych:

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 
... 

Obliczone wartości średnie należy dodać do df w dodatkowej kolumnie ("średnia"), tj. Ta sama średnia wartość dla lat okresu 1, dla tych z okresu 2 itd.

Oto jak powinno to wyglądać:

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 
... 

Każda możliwa ścieżka próbowałem dostał łatwo bardzo skomplikowana - i muszę obliczyć średnie wyniki dla różnych okresach czasu przez ponad 90 krajów ...

wiele wielkie dzięki za pomoc!

Odpowiedz

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

Tytułowe pytanie jest nieco inne niż w prawdziwym pytaniu i można na nie odpowiedzieć za pomocą indeksowania logicznego. Jeśli ktoś chciał tylko średnią dla danego podzbioru powiedzieć year >= 1984 & year <= 1990 będzie się to odbywać poprzez:

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

WOW! Było to niezwykle szybkie i bardzo pomocne. Wielkie dzięki za to super eleganckie rozwiązanie! – TiF

+4

Funkcja 'findInterval' potrzebuje lepszej agencji reklamowej. –

5

Od findInterval wymaga year mają być sortowane (jak to jest w przykładzie) Byłbym skłonny do korzystania cut w sprawa nie jest posortowana [okazało się nie tak, dzięki @DWin]. Dla kompletności się data.table odpowiednik (wagi dla dużych danych) wynosi:

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))] 

lub findInterval prawdopodobnie szybciej stosowany Dwin:

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

To twierdzenie o findInterval jest nieprawidłowe (potwierdzone po testowaniu), ale dzięki za ofertę DT. –

+0

Dzięki za testowanie! – TiF

+1

@DWin. Przepraszam, pomyliłem 'vec' i' x'. Masz rację. –

Powiązane problemy