2015-08-21 17 views
10

Vorrei calcolare i mezzi di un frame di dati per ciascun fattore, ma solo se sono soddisfatte determinate condizioni. Ad esempio, ho questo frame di dati:Calcolo condizionale della media

> df <- data.frame(name = rep(c("A", "B", "C"), 20), 
       variable1 = rep(c(1, 1, 1, 1, 1, NA), 10), 
       variable2 = rep(c(2, NA, 2, 2, 2, 2), 10), 
       variable3 = rep(c(NA, 3, 3, 3, 3, 3), 10)) 

> table(df$name, df$variable1) 

    1 
    A 20 
    B 20 
    C 10 

> table(df$name, df$variable2) 

    2 
    A 20 
    B 10 
    C 20 

> table(df$name, df$variable3) 

    3 
    A 10 
    B 20 
    C 20 

posso facilmente calcolare mezzi per ogni variabile con dplyr in modo seguente:

means <- df %>% 
    group_by(name) %>% 
    summarise_each(funs(mean(., na.rm = TRUE))) 
> means 
Source: local data frame [3 x 4] 

    name variable1 variable2 variable3 
1 A   1   2   3 
2 B   1   2   3 
3 C   1   2   3 

Tuttavia, ciò che voglio è solo calcolare mezzi caso sono 11 o più osservazioni, altrimenti inserisci NA nelle rispettive celle. In altre parole, il risultato dovrebbe essere così:

name variable1 variable2 variable3 
1 A   1   2  NA 
2 B   1  NA   3 
3 C  NA   2   3 

risposta

6

Potremmo creare una funzione (f1) che farà la media if il numero dei non NA valori è maggiore di 11 (sum(!is.na(x))>11) oppure otteniamo NA. Sto usando NA_real_ come il default NA sarebbe di classe logica e potrebbe esserci un conflitto di classe in alcuni pacchetti.

Utilizzando dplyr, abbiamo gruppo da name e utilizzare la funzione (f1) entro summarise_each

f1 <- function(x) if(sum(!is.na(x))>11) mean (x, na.rm=TRUE) else NA_real_ 
library(dplyr) 
df %>% 
    group_by(name) %>% 
    summarise_each(funs(f1)) 

O un approccio simile utilizzando data.table sarebbe quello di convertire il data.frame-data.table (setDT(df)). Noi ciclo attraverso le colonne (lapply(.SD, ..)), utilizziamo la stessa funzione raggruppati per name

library(data.table) 
setDT(df)[, lapply(.SD, f1), by = name] 
# name variable1 variable2 variable3 
#1: A   1   2  NA 
#2: B   1  NA   3 
#3: C  NA   2   3 
+0

E 'stato veloce! Grazie mille. C'è un modo per fare lo stesso in dplyr? Non è una condizione rigorosa, solo per curiosità. –

+0

@DavidArenburg Grazie, stavo aggiornando la funzione. – akrun

+1

@MikhailBalyasin trovi la sintassi 'dplyr' più intuitiva? –

2

Un trasformante alternativa precedentemente i dati da largo a lungo.

library(reshape2) 
df1 <- melt(df, id.vars = c("name")) # From wide to long 
df1 <- df1 %>% group_by(name, variable) %>% 
     filter(n()>10) %>% 
     summarize(mean = mean(value)) 

uscita Formato lungo:

name variable mean 
1 A variable1 1 
2 A variable2 2 
3 A variable3 NA 
4 B variable1 1 
5 B variable2 NA 
6 B variable3 3 
7 C variable1 NA 
8 C variable2 2 
9 C variable3 3 

largo formato di output:

dcast(df1, name ~ variable, value.var = "mean") 

    name variable1 variable2 variable3 
1 A   1   2  NA 
2 B   1  NA   3 
3 C  NA   2   3 
Problemi correlati