2014-12-12 2 views
6

Ho un frame di dati con due variabili numeriche fatcontent e saltcontent più due variabili fattore cond e spezia che descrivono i diversi trattamenti. In questo quadro di dati ogni misura per le varible numeriche è stata presa due volte.Come normalizzare sottogruppi da un frame di dati raggruppati in R

a <- data.frame(cond = rep(c("uncooked", "fried", "steamed", "baked", "grilled"), 
         each = 2, times = 3), 
       spice = rep(c("none", "chilli", "basil"), each = 10), 
       fatcontent = c(4, 5, 6828, 7530, 6910, 7132, 5885, 613, 2845, 2867, 
           25, 18, 2385, 33227, 4233, 4023, 953, 1025, 4465, 5016, 
           5, 5, 10235, 12545, 5511, 5111, 596, 585, 4012, 3633), 
       saltcontent = c(2, 5, 4733, 5500, 5724, 15885, 14885, 217, 193, 148, 
           6, 4, 26738, 24738, 22738, 23738, 267, 256, 1121, 1558, 
           1, 1, 21738, 20738, 26738, 27738, 195, 202, 129, 131) 
       ) 

Ora, desidero nomalise (che significa dividere in questo caso) le variabili numeriche per ogni gruppo di spezie per la media della condizione crudo.
E.g. per un $ spezie == "none"

 cond spice fatcontent saltcontent 
1 uncooked none   4   2 
2 uncooked none   5   5 
3  fried none  6828  4733 
4  fried none  7530  5500 
5 steamed none  6910  5724 
6 steamed none  7132  15885 
7  baked none  5885  14885 
8  baked none  613   217 
9 grilled none  2845   193 
10 grilled none  2867   148 

Dopo la normalizzazione:

 cond spice fatcontent saltcontent 
1 uncooked none 0.8888889 0.5714286 
2 uncooked none 1.1111111 1.4285714 
3  fried none 1517.3333333 1352.2857143 
4  fried none 1673.3333333 1571.4285714 
5 steamed none 1535.5555556 1635.4285714 
6 steamed none 1584.8888889 4538.5714286 
7  baked none 1307.7777778 4252.8571429 
8  baked none 136.2222222 62.0000000 
9 grilled none 632.2222222 55.1428571 
10 grilled none 637.1111111 42.2857143 

Le mie domande è come posso fare questo per tutti i gruppi e le variabili nella cornice di dati? Presumo che potrei usare il pacchetto dplyr ma non sono sicuro di quale sia il modo migliore. Apprezzo qualsiasi aiuto!

risposta

3

Penso che questo sia quello che stai cercando. Si desidera trovare la media per ciascuna condizione delle spezie utilizzando punti dati non cotti. Questo è qualcosa che ho fatto nel mio primo passo. Quindi, volevo aggiungere e saltmean in ana al frame di dati, a. Se i tuoi dati sono davvero enormi, questo potrebbe non essere un modo efficiente per la memoria. Ma, ho usato left_join per unire ana e a. Quindi, ho effettuato la divisione in mutate per ciascuna condizione delle spezie. Infine, ho lasciato cadere due colonne per mettere in ordine i risultati usando select.

### Find mean for each spice condition using uncooked data points     
ana <- group_by(filter(a, cond == "uncooked"), spice) %>% 
     summarise(fatmean = mean(fatcontent), saltmean = mean(saltcontent)) 

# spice fatmean saltmean 
#1 basil  5.0  1.0 
#2 chilli 21.5  5.0 
#3 none  4.5  3.5 

left_join(a, ana, by = "spice") %>% 
group_by(spice) %>% 
mutate(fatcontent = fatcontent/fatmean, 
     saltcontent = saltcontent/saltmean) %>% 
select(-c(fatmean, saltmean)) 

# A part of the results 
#  cond spice fatcontent saltcontent 
#1 uncooked none 0.8888889 0.5714286 
#2 uncooked none 1.1111111 1.4285714 
#3  fried none 1517.3333333 1352.2857143 
#4  fried none 1673.3333333 1571.4285714 
#5 steamed none 1535.5555556 1635.4285714 
#6 steamed none 1584.8888889 4538.5714286 
#7  baked none 1307.7777778 4252.8571429 
#8  baked none 136.2222222 62.0000000 
#9 grilled none 632.2222222 55.1428571 
#10 grilled none 637.1111111 42.2857143 

Se fai tutte le cose in una tubazione, sarebbe qualcosa di simile:

group_by(filter(a, cond == "uncooked"), spice) %>% 
    summarise(fatmean = mean(fatcontent), saltmean = mean(saltcontent)) %>% 
    left_join(a, ., by = "spice") %>% #right_join is possible with the dev dplyr 
    group_by(spice) %>% 
    mutate(fatcontent = fatcontent/fatmean, 
      saltcontent = saltcontent/saltmean) %>% 
    select(-c(fatmean, saltmean)) 
+0

Grazie a jazurro, questo è esattamente quello che volevo fare. Saluti Alex – karnowski

+0

@karnowski Siete i benvenuti. :) Come prima domanda, questa è stata scritta molto bene! – jazzurro

2

Tutto quello che dovete fare è di gruppo sia la condizione e di spezie, in questo modo:

library(dplyr) 
a %>% group_by(spice, cond) %>% 
    mutate(fat.norm = fatcontent/mean(fatcontent), 
     salt.norm = saltcontent/mean(saltcontent)) 

# Source: local data frame [90 x 6] 
# Groups: spice, cond 
# 
#  cond spice fatcontent saltcontent fat.norm salt.norm 
# 1 uncooked none   4   2 0.8888889 0.57142857 
# 2 uncooked none   5   5 1.1111111 1.42857143 
# 3  fried none  6828  4733 0.9511074 0.92504642 
# 4  fried none  7530  5500 1.0488926 1.07495358 
# 5 steamed none  6910  5724 0.9841903 0.52977926 
# 6 steamed none  7132  15885 1.0158097 1.47022074 
# 7  baked none  5885  14885 1.8113266 1.97126208 
# 8  baked none  613   217 0.1886734 0.02873792 
# 9 grilled none  2845   193 0.9961485 1.13196481 
# 10 grilled none  2867   148 1.0038515 0.86803519 

In alternativa, se non si desidera specificare ogni colonna, è possibile utilizzare mutate_each o summarise_each:

group.norm <- function(x) { 
    x/mean(x) 
} 

a %>% group_by(spice, cond) %>% 
    mutate_each(funs(group.norm)) 

È possibile escludere le colonne o specificare solo le colonne specifiche mutate_each() pure, come mutate_each(funs(group.norm), -notthisone) o mutate_each(funs(group.norm), onlythisone)

+0

Ack, ho letto male l'OP. Questo si normalizza solo con la media del gruppo, non con la media non cotta. @ La risposta di jazzurro è giusta. – Andrew

4

Un modo succinto per normalizzare i dati potrebbe essere quella di includere il "crudo" condizione giusta nel mezzo calcolo quindi non è necessario filtrare, riepilogare, unire e ricalcolare. Fare questo con mutate_each significa che devi solo digitarlo una volta.

group_by(a, spice) %>% 
    mutate_each(funs(./mean(.[cond == "uncooked"])), -cond) 

#Source: local data frame [30 x 4] 
#Groups: spice 
# 
#  cond spice fatcontent saltcontent 
#1 uncooked none 0.8888889 5.714286e-01 
#2 uncooked none 1.1111111 1.428571e+00 
#3  fried none 1517.3333333 1.352286e+03 
#4  fried none 1673.3333333 1.571429e+03 
#5 steamed none 1535.5555556 1.635429e+03 
#6 steamed none 1584.8888889 4.538571e+03 
#7  baked none 1307.7777778 4.252857e+03 
#8  baked none 136.2222222 6.200000e+01 
#9 grilled none 632.2222222 5.514286e+01 
#10 grilled none 637.1111111 4.228571e+01 
# ... etc 
+0

Super conciso! È grandioso +1. – jazzurro