Calcolo della media e deviazione standard per gruppo per più variabili in un data.frame

Modifica – Questa domanda era originariamente intitolata <>


Sto solo imparando R e sto cercando di trovare modi per applicarlo per aiutare gli altri nella mia vita. Come test case, sto lavorando per rimodellare alcuni dati e ho difficoltà a seguire gli esempi che ho trovato online. Quello che sto iniziando con sembra questo:

ID Obs 1 Obs 2 Obs 3 1 43 48 37 1 27 29 22 1 36 32 40 2 33 38 36 2 29 32 27 2 32 31 35 2 25 28 24 3 45 47 42 3 38 40 36 

E quello che voglio finire sarà simile a questo:

 ID Obs 1 mean Obs 1 std dev Obs 2 mean Obs 2 std dev 1 xxxx 2 xxxx 3 xxxx 

E così via. Ciò di cui non sono sicuro è se ho bisogno di ulteriori informazioni nei miei dati di lunga durata, o cosa. Immagino che la parte matematica (trovare la media e le deviazioni standard) sarà la parte facile, ma non sono stato in grado di trovare un modo che sembra funzionare per rimodellare correttamente i dati per iniziare su quel processo.

Grazie mille per qualsiasi aiuto.

Questo è un problema di aggregazione, non un problema di rimodellamento come la domanda originariamente suggerita: desideriamo aggregare ogni colonna in una deviazione media e standard per ID. Ci sono molti pacchetti che gestiscono tali problemi. Nella base di R può essere fatto usando un aggregate come questo (supponendo che DF sia il frame di dati di input):

 ag <- aggregate(. ~ ID, DF, function(x) c(mean = mean(x), sd = sd(x))) 

Nota 1: un commentatore ha sottolineato che ag è un frame di dati per il quale alcune colonne sono matrici. Sebbene all'inizio possa sembrare strano, in realtà semplifica l'accesso. ag ha lo stesso numero di colonne dell'input DF . La sua prima colonna ag[[1]] è ID e la colonna ith del resto ag[[i+1]] (o equivalanetly ag[-1][[i]] ) è la matrice delle statistiche per l'osservazione di input ith colonna. Se si desidera accedere alla statistica j dell'osservazione è quindi ag[[i+1]][, j] che può anche essere scritto come ag[-1][[i]][, j] .

D'altra parte, supponiamo che ci siano k colonne di statistica per ogni osservazione nell'input (dove k = 2 nella domanda). Quindi, se appiattiamo l'output per accedere alla statistica jth della colonna di osservazione ith, dobbiamo usare l' ag[[k*(i-1)+j+1]] più complesso ag[[k*(i-1)+j+1]] o equivalentemente ag[-1][[k*(i-1)+j]] .

Ad esempio, confronta la semplicità della prima espressione con la seconda:

 ag[-1][[2]] ## mean sd ## [1,] 36.333 10.2144 ## [2,] 32.250 4.1932 ## [3,] 43.500 4.9497 ag_flat <- do.call("data.frame", ag) # flatten ag_flat[-1][, 2 * (2-1) + 1:2] ## Obs_2.mean Obs_2.sd ## 1 36.333 10.2144 ## 2 32.250 4.1932 ## 3 43.500 4.9497 

Nota 2: l'input in forma riproducibile è:

 Lines <- "ID Obs_1 Obs_2 Obs_3 1 43 48 37 1 27 29 22 1 36 32 40 2 33 38 36 2 29 32 27 2 32 31 35 2 25 28 24 3 45 47 42 3 38 40 36" DF <- read.table(text = Lines, header = TRUE) 

Ecco probabilmente il modo più semplice per farlo (con un esempio riproducibile ):

 library(plyr) df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9)) ddply(df, .(ID), summarize, Obs_1_mean=mean(Obs_1), Obs_1_std_dev=sd(Obs_1), Obs_2_mean=mean(Obs_2), Obs_2_std_dev=sd(Obs_2)) ID Obs_1_mean Obs_1_std_dev Obs_2_mean Obs_2_std_dev 1 1 -0.13994642 0.8258445 -0.15186380 0.4251405 2 2 1.49982393 0.2282299 0.50816036 0.5812907 3 3 -0.09269806 0.6115075 -0.01943867 1.3348792 

EDIT: il seguente approccio ti consente di risparmiare un sacco di digitazione quando si ha a che fare con molte colonne.

 ddply(df, .(ID), colwise(mean)) ID Obs_1 Obs_2 Obs_3 1 1 -0.3748831 0.1787371 1.0749142 2 2 -1.0363973 0.0157575 -0.8826969 3 3 1.0721708 -1.1339571 -0.5983944 ddply(df, .(ID), colwise(sd)) ID Obs_1 Obs_2 Obs_3 1 1 0.8732498 0.4853133 0.5945867 2 2 0.2978193 1.0451626 0.5235572 3 3 0.4796820 0.7563216 1.4404602 

Ci sono diversi modi per farlo. reshape2 è un pacchetto utile. Personalmente, mi piace usare data.table

Di seguito è un passo-passo

Se myDF è il tuo data.frame :

 library(data.table) DT <- data.table(myDF) DT # this will get you your mean and SD's for each column DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x)))] # adding a `by` argument will give you the groupings DT[, sapply(.SD, function(x) list(mean=mean(x), sd=sd(x))), by=ID] # If you would like to round the values: DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID] # If we want to add names to the columns wide <- setnames(DT[, sapply(.SD, function(x) list(mean=round(mean(x), 3), sd=round(sd(x), 3))), by=ID], c("ID", sapply(names(DT)[-1], paste0, c(".men", ".SD")))) wide ID Obs.1.men Obs.1.SD Obs.2.men Obs.2.SD Obs.3.men Obs.3.SD 1: 1 35.333 8.021 36.333 10.214 33.0 9.644 2: 2 29.750 3.594 32.250 4.193 30.5 5.916 3: 3 41.500 4.950 43.500 4.950 39.0 4.243 

Inoltre, questo può o non può essere d'aiuto

 > DT[, sapply(.SD, summary), .SDcols=names(DT)[-1]] Obs.1 Obs.2 Obs.3 Min. 25.00 28.00 22.00 1st Qu. 29.00 31.00 27.00 Median 33.00 32.00 36.00 Mean 34.22 36.11 33.22 3rd Qu. 38.00 40.00 37.00 Max. 45.00 48.00 42.00 

Ecco un’altra risposta data.table risposte data.table , utilizzando i dati di @ Carson, che è un po ‘più leggibile (e anche un po’ più veloce, a causa dell’uso di lapply anziché di sapply ):

 library(data.table) set.seed(1) dt = data.table(ID=c(1:3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9)) dt[, c(mean = lapply(.SD, mean), sd = lapply(.SD, sd)), by = ID] # ID mean.Obs_1 mean.Obs_2 mean.Obs_3 sd.Obs_1 sd.Obs_2 sd.Obs_3 #1: 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961 #2: 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338 #3: 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692 

Aggiungo la soluzione dplyr .

 set.seed(1) df <- data.frame(ID=rep(1:3, 3), Obs_1=rnorm(9), Obs_2=rnorm(9), Obs_3=rnorm(9)) library(dplyr) df %>% group_by(ID) %>% summarise_each(funs(mean, sd)) # ID Obs_1_mean Obs_2_mean Obs_3_mean Obs_1_sd Obs_2_sd Obs_3_sd # (int) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) # 1 1 0.4854187 -0.3238542 0.7410611 1.1108687 0.2885969 0.1067961 # 2 2 0.4171586 -0.2397030 0.2041125 0.2875411 1.8732682 0.3438338 # 3 3 -0.3601052 0.8195368 -0.4087233 0.8105370 0.3829833 1.4705692