2017-04-03 1 views
0

Mein Dataset das folgende Formularberechnen bedingten Mittelwert eines Datenrahmen-Vektor

Name     year       val  
”a”      1       25  
”a”      1       75  
”a”      2       20  
”a”      2       40  
”a”      2       60  
”a”      3       50  

”b”      1       20  
”b”      2       10  
”b”      2       20  
”b”      2       30 
”b”      3       40 
”b”      3       60 

So besteht aus einem Namen, Jahr und einen Wert hat. Ich möchte den Durchschnitt der Werte (val) für jedes Jahr finden und gruppiert durch Name. Das heißt, ich bin interessiert

Name     year   average    terms in the average 
”a”      1   50      2 
”a”      2   40      3 
”a”      3   NA      1 

”b”      1   NA      1 
”b”      2   20      3 
”b”      3   50      2 

Im Durchschnitt in immer -column es NA sagt, wenn es weniger als 2 Begriffe und ich habe weiterhin eine vierte Spalte, die die Anzahl der Begriffe enthält, die in dem Durchschnitt hinzugefügt.

Dies ist eine ganze Reihe von Operationen und sie können natürlich in einem for-Loop durchgeführt werden. Aber was ist das professionelle R -way, um ein solches Problem zu lösen?


Die Daten

df = structure(list(name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L), .Label = c("a", "b"), class = "factor"), 
    year = c(1, 1, 2, 2, 2, 3, 1, 2, 2, 2, 3, 3), val = c(25, 
    75, 20, 40, 60, 50, 20, 10, 20, 30, 40, 60)), .Names = c("name", 
"year", "val"), row.names = c(NA, -12L), class = "data.frame") 
+1

Sollte nicht der Durchschnitt für name = 'a' year = 2 40 sein? – G5W

+0

Der von Ihnen bereitgestellte df ist kein data.frame. – Frank

Antwort

2

Die dplyr Weg:


library(dplyr) 

df %>% 
    group_by(name, year) %>% 
    summarize(average = ifelse(n() < 2, NA, mean(val)), 
      `terms in the average` = n()) 
#> Source: local data frame [6 x 4] 
#> Groups: name [?] 
#> 
#>  Name year average `terms in the average` 
#> <fctr> <int> <dbl>     <int> 
#> 1 ”a”  1  50      2 
#> 2 ”a”  2  40      3 
#> 3 ”a”  3  NA      1 
#> 4 ”b”  1  NA      1 
#> 5 ”b”  2  20      3 
#> 6 ”b”  3  50      2 
2

Eine Möglichkeit, mit data.table:

library(data.table) 
#group by name and year and calculate average 
df2 <- setDT(df)[, list(average = mean(val), terms = .N), by = c('Name', 'year')] 
#NA if terms less than 2 
df2[terms < 2, average := NA] 

Ausgang:

Name year average terms 
1: a 1  50  2 
2: a 2  40  3 
3: a 3  NA  1 
4: b 1  NA  1 
5: b 2  20  3 
6: b 3  50  2 
+1

Sie raten richtig @Frank. Manchmal vergesse ich, wie viel einfacher es ist. Vielen Dank! – LyzandeR

1
aggregate(df$val, by = list(df$name, df$year), function(x) 
         c(mean = mean(x)*NA^(!length(x)>1), n = length(x))) 
# Group.1 Group.2 x.mean x.n 
#1  a  1  50 2 
#2  b  1  NA 1 
#3  a  2  40 3 
#4  b  2  20 3 
#5  a  3  NA 1 
#6  b  3  50 2 
+0

OP will zwei neue Spalten: die mittlere sowie die Länge, sieht aus wie. – Frank

Verwandte Themen