2016-05-26 13 views
3

Wie gruppiere ich nach Spalten, berechne dann den Mittelwert und die Standardabweichung jeder anderen Spalte in R?Gruppieren Sie nach Spalten, berechnen Sie dann Mittelwert und SD jeder anderen Spalte in R

Betrachten Sie als Beispiel den berühmten Iris-Datensatz. Ich möchte etwas Ähnliches wie Gruppierung nach Art, tun dann berechnen Sie den Mittelwert und SD der Blütenblatt/Sepal Länge/Breite Messungen. Ich weiß, dass dies etwas mit Split-Apply-Combine, zu tun hat, aber ich bin mir nicht sicher, wie man von dort weitergeht.

Was kann ich kommen mit:

require(plyr) 

x <- ddply(iris, .(Species), summarise, 
    Sepal.Length.Mean = mean(Sepal.Length), 
    Sepal.Length.Sd = sd(Sepal.Length), 
    Sepal.Width.Mean = mean(Sepal.Width), 
    Sepal.Width.Sd = sd(Sepal.Width), 
    Petal.Length.Mean = mean(Petal.Length), 
    Petal.Length.Sd = sd(Petal.Length), 
    Petal.Width.Mean = mean(Petal.Width), 
    Petal.Width.Sd = sd(Petal.Width)) 

    Species Sepal.Length.Mean Sepal.Length.Sd Sepal.Width.Mean Sepal.Width.Sd 
1  setosa    5.006  0.3524897   3.428  0.3790644 
2 versicolor    5.936  0.5161711   2.770  0.3137983 
3 virginica    6.588  0.6358796   2.974  0.3224966 
    Petal.Length.Mean Petal.Length.Sd Petal.Width.Mean Petal.Width.Sd 
1    1.462  0.1736640   0.246  0.1053856 
2    4.260  0.4699110   1.326  0.1977527 
3    5.552  0.5518947   2.026  0.2746501 

gewünschte Ausgabe:

z <- data.frame(setosa = c(5.006, 0.3524897, 3.428, 0.3790644, 
          1.462, 0.1736640, 0.246, 0.1053856), 
       versicolor = c(5.936, 0.5161711, 2.770, 0.3137983, 
           4.260, 0.4699110, 1.326, 0.1977527), 
       virginica = c(6.588, 0.6358796, 2.974, 0.3225966, 
           5.552, 0.5518947, 2.026, 0.2746501)) 
rownames(z) <- c('Sepal.Length.Mean', 'Sepal.Length.Sd', 
       'Sepal.Width.Mean', 'Sepal.Width.Sd', 
       'Petal.Length.Mean', 'Petal.Length.Sd', 
       'Petal.Width.Mean', 'Petal.Width.Sd') 
        setosa versicolor virginica 
Sepal.Length.Mean 5.0060000 5.9360000 6.5880000 
Sepal.Length.Sd 0.3524897 0.5161711 0.6358796 
Sepal.Width.Mean 3.4280000 2.7700000 2.9740000 
Sepal.Width.Sd 0.3790644 0.3137983 0.3225966 
Petal.Length.Mean 1.4620000 4.2600000 5.5520000 
Petal.Length.Sd 0.1736640 0.4699110 0.5518947 
Petal.Width.Mean 0.2460000 1.3260000 2.0260000 
Petal.Width.Sd 0.1053856 0.1977527 0.2746501 
+0

Ich denke, der Wert der Zelle „setosa“/„Sepal.Length.Mean“ 5,006 sein sollte, nicht 0,5006 in dem „gewünschten Ausgang“ (sieht aus wie ein Tippfehler). Ich werde die Frage bearbeiten, um dies zu beheben, wenn niemand dagegen ist –

Antwort

8

Wir können versuchen, mit dplyr

library(dplyr) 
res <- iris %>% 
     group_by(Species) %>% 
     summarise_each(funs(mean, sd)) 
`colnames<-`(t(res[-1]), as.character(res$Species)) 
#      setosa versicolor virginica 
#Sepal.Length_mean 5.0060000 5.9360000 6.5880000 
#Sepal.Width_mean 3.4280000 2.7700000 2.9740000 
#Petal.Length_mean 1.4620000 4.2600000 5.5520000 
#Petal.Width_mean 0.2460000 1.3260000 2.0260000 
#Sepal.Length_sd 0.3524897 0.5161711 0.6358796 
#Sepal.Width_sd 0.3790644 0.3137983 0.3224966 
#Petal.Length_sd 0.1736640 0.4699110 0.5518947 
#Petal.Width_sd 0.1053856 0.1977527 0.2746501 

Oder wie @ Steven Beaupre erwähnt in den Kommentaren kann die Ausgabe durch Umformen mit spread

library(tidyr) 
iris %>% 
    group_by(Species) %>% 
    summarise_each(funs(mean, sd)) %>% 
    gather(key, value, -Species) %>% 
    spread(Species, value) 
+4

Um die Matrix zu transponieren, könnten Sie tun: 'Iris%>% group_by (Species)%>% summarise_each (Spaß (Mittelwert, SD))%>% sammeln (Schlüssel, Wert, -Species)%>% Spread (Art, Wert) ' –

3

Hier ist der traditionelle plyr Ansatz erhalten werden. Es verwendet colwise, um Zusammenfassungsstatistiken für alle Spalten zu berechnen.

means <- ddply(iris, .(Species), colwise(mean)) 
sds <- ddply(iris, .(Species), colwise(sd)) 
merge(means, sds, by = "Species", suffixes = c(".mean", ".sd")) 
1

Wenn Sie data.table aus Leistungsgründen verwenden möchten können Sie diese versuchen (keine Angst - mehr Kommentare als Code ;-) Ich habe versucht, alle Leistungs kritischen Stellen zu optimieren.

library(data.table) 
dt <- as.data.table(iris) 

# Helper function similar to "colwise" of package "plyr": 
# Apply a function "func" to each column of the data.table "data" 
# and append the "suffix" string to the result column name. 
colwise.dt <- function(data, func, suffix) 
{ 
    result <- lapply(data, func)          # apply the function to each column of the data table 
    setDT(result)              # convert the result list into a data table efficiently ("by ref") 
    setnames(result, names(result), paste0(names(result), suffix)) # append suffix to each column name efficiently ("by ref"). "setnames" requires a data.table 
} 

wide.result <- dt[, c(colwise.dt(.SD, mean, ".mean"), colwise.dt(.SD, sd, ".sd")), by=.(Species)] 
# Note: .SD is a data.table containing the subset of dt's data for each group (Species), excluding any columns used in "by" (here: Species column) 

# Now transpose the result 
long.result <- melt(wide.result, id.vars="Species") 

# Now transform into one column per group 
final.result <- dcast(long.result, variable ~ Species) 

wide.result ist:

 Species Sepal.Length.mean Sepal.Width.mean Petal.Length.mean Petal.Width.mean Sepal.Length.sd Sepal.Width.sd Petal.Length.sd Petal.Width.sd 
1:  setosa    5.006   3.428    1.462   0.246  0.3524897  0.3790644  0.1736640  0.1053856 
2: versicolor    5.936   2.770    4.260   1.326  0.5161711  0.3137983  0.4699110  0.1977527 
3: virginica    6.588   2.974    5.552   2.026  0.6358796  0.3224966  0.5518947  0.2746501 

long.result ist:

 Species   variable  value 
1:  setosa Sepal.Length.mean 5.0060000 
2: versicolor Sepal.Length.mean 5.9360000 
3: virginica Sepal.Length.mean 6.5880000 
4:  setosa Sepal.Width.mean 3.4280000 
5: versicolor Sepal.Width.mean 2.7700000 
6: virginica Sepal.Width.mean 2.9740000 
7:  setosa Petal.Length.mean 1.4620000 
8: versicolor Petal.Length.mean 4.2600000 
9: virginica Petal.Length.mean 5.5520000 
10:  setosa Petal.Width.mean 0.2460000 
11: versicolor Petal.Width.mean 1.3260000 
12: virginica Petal.Width.mean 2.0260000 
13:  setosa Sepal.Length.sd 0.3524897 
14: versicolor Sepal.Length.sd 0.5161711 
15: virginica Sepal.Length.sd 0.6358796 
16:  setosa Sepal.Width.sd 0.3790644 
17: versicolor Sepal.Width.sd 0.3137983 
18: virginica Sepal.Width.sd 0.3224966 
19:  setosa Petal.Length.sd 0.1736640 
20: versicolor Petal.Length.sd 0.4699110 
21: virginica Petal.Length.sd 0.5518947 
22:  setosa Petal.Width.sd 0.1053856 
23: versicolor Petal.Width.sd 0.1977527 
24: virginica Petal.Width.sd 0.2746501 

final.result ist:

  variable setosa versicolor virginica 
1: Sepal.Length.mean 5.0060000 5.9360000 6.5880000 
2: Sepal.Width.mean 3.4280000 2.7700000 2.9740000 
3: Petal.Length.mean 1.4620000 4.2600000 5.5520000 
4: Petal.Width.mean 0.2460000 1.3260000 2.0260000 
5: Sepal.Length.sd 0.3524897 0.5161711 0.6358796 
6: Sepal.Width.sd 0.3790644 0.3137983 0.3224966 
7: Petal.Length.sd 0.1736640 0.4699110 0.5518947 
8: Petal.Width.sd 0.1053856 0.1977527 0.2746501 

Der einzige Unterschied zu den gewünschten Ausgang ist t Er final Ergebnisse enthält die Wertnamen in der ersten Spalte mit dem Namen variable statt diese in den Zeilennamen zu speichern. Dies könnte durch die Einstellung der Zeilennamen in der ersten Spalte und Entfernen die erste Spalte erfolgen ...

1

durch die Antworten inspiriert, dachte ich, eine Lösung aus, die auch funktioniert, nur dplyr und tidyr Funktionen.

require(tidyr) 
require(dplyr) 

x <- iris %>% 
    gather(var, value, -Species) 
print(tbl_df(x)) 

# Compute the mean and sd for each dimension 
x <- x %>% 
    group_by(Species, var) %>% 
    summarise(mean = mean(value), sd = sd(value)) %>% 
    ungroup 
print(tbl_df(x)) 

# Convert the data frame from wide form to long form 
x <- x %>% 
    gather(stat, value, mean:sd) 
print(tbl_df(x)) 

# Combine the variables "var" and "stat" into a single variable 
x <- x %>% 
    unite(var, var, stat, sep = '.') 
print(tbl_df(x)) 

# Convert the data frame from long form to wide form 
x <- x %>% 
    spread(Species, value) 
print(tbl_df(x))