2016-11-02 4 views
2

Ich versuche, mehrere Statistiken für einen Datenrahmen zu berechnen.dplyr - Mehrere zusammenfassende Funktionen

Ich versuchte dplyr 's summarise_each. Die Ergebnisse werden jedoch in einer einfachen Zeile zurückgegeben, wobei der Name der Funktion als Suffix hinzugefügt wird.

Gibt es einen direkten Weg - mit dplyr oder Basis r - wo kann ich die Ergebnisse in einem Datenrahmen, mit den Spalten als die Spalten des Datenrahmens und die Zeilen als die Zusammenfassung Funktionen?

library(dplyr) 

df = data.frame(A = sample(1:100, 20), 
       B = sample(110:200, 20), 
       C = sample(c(0,1), 20, replace = T)) 

df %>% summarise_each(funs(min, max)) 
# A_min B_min C_min A_max B_max C_max 
# 1 13 117  0 98 188  1 

# Desired format 
summary(df) 
# A    B    C  
# Min. :13.00 Min. :117.0 Min. :0.00 
# 1st Qu.:34.75 1st Qu.:134.2 1st Qu.:0.00 
# Median :45.00 Median :148.0 Median :1.00 
# Mean :52.35 Mean :149.9 Mean :0.65 
# 3rd Qu.:62.50 3rd Qu.:168.8 3rd Qu.:1.00 
# Max. :98.00 Max. :188.0 Max. :1.00 
+1

der Nähe von diesem? http://Stackoverflow.com/q/38892219/3871924 – agenis

+0

@agenis Danke! Ja, das ist knapp. Ich habe mich nur gefragt, ob es einen einfacheren Weg gibt. – Deena

+0

'summarise' gibt eine Zeile pro Gruppe zurück, so dass ohne Gruppierung eine Zeile zurückgegeben wird. – Axeman

Antwort

0

Es ist nicht der einzige Weg zu gehen, aber Sie könnten Ihre data.frame neu zu gestalten, wie Sie dplyr und tidyr verwenden möchten. (Und stringr oder andere zu trimmen Charakter.)

library(dplyr) 

df = data.frame(A = sample(1:100, 20), 
       B = sample(110:200, 20), 
       C = sample(c(0,1), 20, replace = T)) 

as_data_frame(summary(df)) %>% 
    # some blank character could be trim 
    mutate(Var2 = stringr::str_trim(Var2)) %>% 
    # you don't need Var1 
    select(-Var1) %>% 
    # Get the type of summary and the value 
    tidyr::separate(n, c("Type", "value"), sep = ":") %>% 
    # Convert value to numeric 
    mutate(value = as.numeric(value)) %>% 
    # reshape as you wish 
    tidyr::spread(Var2, value, drop = T) 
#> # A tibble: 6 x 4 
#>  Type  A  B  C 
#> * <chr> <dbl> <dbl> <dbl> 
#> 1 1st Qu. 36.25 122.2 1.00 
#> 2 3rd Qu. 77.25 164.5 1.00 
#> 3 Max. 95.00 193.0 1.00 
#> 4 Mean 57.30 144.6 0.85 
#> 5 Median 63.00 143.5 1.00 
#> 6 Min.  8.00 111.0 0.00 
2

Wie wäre:

library(tidyr) 
gather(df) %>% group_by(key) %>% summarise_all(funs(min, max)) 
# A tibble: 3 × 3 
    key min max 
    <chr> <dbl> <dbl> 
1  A  2 92 
2  B 111 194 
3  C  0  1 
2

Mit dem data.frame Sie vorgeschlagen, und mit Hilfe der Bibliothek purrr

library(purrr) 
out <- df %>% map(~summary(.)) %>% rbind.data.frame 
row.names(out) <- c("Min.", "1st Qu.", "Median", "Mean", "3rd Qu.", "Max.") 
####    A  B C 
#### Min.  7.00 110.0 0.0 
#### 1st Qu. 36.75 132.5 0.0 
#### Median 53.50 143.5 0.5 
#### Mean 55.45 151.8 0.5 
#### 3rd Qu. 82.00 167.0 1.0 
#### Max. 99.00 199.0 1.0 

Da gehen Sie hin. Lassen Sie mich nur erwähnen, dass dieser Code nur für Eingabedaten.frame mit 100% numerischen Variablen funktioniert. Es wird ein Fehler zurückgegeben, wenn es beispielsweise eine Zeichen-/Faktorvariable gibt, da die Ausgabe der Zusammenfassung sehr unterschiedlich ist.

0

Ein Ansatz ohne tidyr noch dplyr mit:

df <- data.frame(A = sample(1:100, 20), 
       B = sample(110:200, 20), 
       C = sample(c(0,1), 20, replace = T)) 
df %>% 
    lapply(summary) %>% 
    do.call("rbind", .) 

Ausgang:

Min. 1st Qu. Median Mean 3rd Qu. Max. 
A 9 32.5 50.5 49.65 70.25 84 
B 116 137.2 162.5 157.70 178.20 196 
C 0  0.0 0.0 0.45 1.00 1 

Wenn Sie es mit dplyr tun wollen, versuchen:

df %>% 
    gather(attribute, value) %>% 
    group_by(attribute) %>% 
    do(as.data.frame(as.list(summary(.$value)))) 

Ausgang:

Source: local data frame [3 x 7] 
Groups: attribute [3] 

    attribute Min. X1st.Qu. Median Mean X3rd.Qu. Max. 
     <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1   A  9  32.5 50.5 49.65 70.25 84 
2   B 116 137.2 162.5 157.70 178.20 196 
3   C  0  0.0 0.0 0.45  1.00  1 
0

Vielen Dank für Ihre Hilfe! Nach einigem Rosinenpflücken benutzte ich die folgende Methode.

# Dataframe 
df = data.frame(A = sample(1:100, 20), 
       B = sample(110:200, 20), 
       C = sample(c(0,1), 20, replace = T)) 

# Add summary functions to a list 
summaryFns = list(
    NA.n = function(x) sum(is.na(x)), 
    NA.percent = function(x) sum(is.na(x))/length(x), 
    unique.n = function(x) ifelse(sum(is.na(x)) > 0, length(unique(x)) - 1, length(unique(x))), 
    min = function(x) min(x, na.rm=TRUE), 
    max = function(x) max(x, na.rm=TRUE)) 


# Summarise data frame with each function 
# Using dplyr: 
library(dplyr) 
sapply(summaryFns, function(fn){df %>% summarise_all(fn)}) 
# NA.n NA.percent unique.n min max 
# A 0 0   20  1 98 
# B 0 0   20  114 200 
# C 0 0   2  0 1 

# Using base-r: 
sapply(summaryFns, function(fn){sapply(df, fn)}) 
#  NA.n NA.percent unique.n min max 
# A 0   0  20 1 98 
# B 0   0  20 114 200 
# C 0   0  2 0 1 

Ich denke, dass die direkteste und flexibelste Methode ist.
Weitere Kommentare, Änderungen und Vorschläge sind willkommen.

6

Warum nicht einfach einfach mit summary verwenden?

sapply(df, summary) 

gibt:

  A  B C 
Min.  1.00 112.0 0.00 
1st Qu. 23.75 134.5 0.00 
Median 57.00 148.5 1.00 
Mean 50.15 149.9 0.55 
3rd Qu. 77.50 167.2 1.00 
Max. 94.00 191.0 1.00 

Um einen Datenrahmen zurück, nur wickeln Sie den sapply Anruf in data.frame(): data.frame(sapply(df, summary)).Wenn Sie Zusammenfassung statisticnames in einer Spalte halten möchten, können Sie sie mit rownames(df) mit df$rn <- rownames(df) oder verwenden extrahieren Sie die keep.rownames -parameter von data.table:

library(data.table) 
dt <- data.table(sapply(df, summary), keep.rownames = TRUE) 

die gibt:

> dt 
     rn  A  B C 
1: Min. 11.00 113.0 0.0 
2: 1st Qu. 21.50 126.8 0.0 
3: Median 55.00 138.0 0.5 
4: Mean 53.65 145.2 0.5 
5: 3rd Qu. 83.25 160.5 1.0 
6: Max. 98.00 193.0 1.0 
Verwandte Themen