Mehrere Variablen pro Gruppe aggregieren / zusammenfassen (z. B. Summe, Mittelwert)

152

Von einem Datenrahmen, gibt es eine einfache Möglichkeit , aggregieren ( sum, mean, maxet c) gleichzeitig mehrere Variablen?

Nachfolgend einige Beispieldaten:

library(lubridate)
days = 365*2
date = seq(as.Date("2000-01-01"), length = days, by = "day")
year = year(date)
month = month(date)
x1 = cumsum(rnorm(days, 0.05)) 
x2 = cumsum(rnorm(days, 0.05))
df1 = data.frame(date, year, month, x1, x2)

Ich möchte die Variablen x1und x2aus dem df2Datenrahmen gleichzeitig nach Jahr und Monat aggregieren . Der folgende Code aggregiert die x1Variable, aber ist es auch möglich, die x2Variable gleichzeitig zu aggregieren ?

### aggregate variables by year month
df2=aggregate(x1 ~ year+month, data=df1, sum, na.rm=TRUE)
head(df2)

Anregungen wäre sehr dankbar.

MikeTP
quelle

Antworten:

45

Woher kommt diese year()Funktion?

Sie können das reshape2Paket auch für diese Aufgabe verwenden:

require(reshape2)
df_melt <- melt(df1, id = c("date", "year", "month"))
dcast(df_melt, year + month ~ variable, sum)
#  year month         x1           x2
1  2000     1  -80.83405 -224.9540159
2  2000     2 -223.76331 -288.2418017
3  2000     3 -188.83930 -481.5601913
4  2000     4 -197.47797 -473.7137420
5  2000     5 -259.07928 -372.4563522
EDi
quelle
8
Die recastFunktion (auch von reshape2) integriert die meltund dcastFunktion auf einmal für Aufgaben wie diese:recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))
Jaap
184

Ja, in Ihrem formulakönnen Sie cbinddie numerischen Variablen aggregieren:

aggregate(cbind(x1, x2) ~ year + month, data = df1, sum, na.rm = TRUE)
   year month         x1          x2
1  2000     1   7.862002   -7.469298
2  2001     1 276.758209  474.384252
3  2000     2  13.122369 -128.122613
...
23 2000    12  63.436507  449.794454
24 2001    12 999.472226  922.726589

Siehe ?aggregatedas formulaArgument und die Beispiele.

Andrie
quelle
3
Kann die cbind dynamische Variablen verwenden?
pdb
14
Es ist erwähnenswert, dass, wenn eine der Variablen in der Bindung eine NA hat, die Zeile für jede Variable in der Bindung gelöscht wird. Dies ist nicht das Verhalten, das ich erwartet hatte.
pdb
1
Was ist, wenn ich anstelle von x1 und x2 alle verbleibenden Variablen (außer Jahr, Monat) verwenden möchte
Clock Slave
7
@ClockSlave, dann müssen Sie nur .auf der LHS verwenden. aggregate(. ~ year + month, df1, sum, na.rm = TRUE). In diesem Beispiel macht sum"Datum" allerdings keinen Sinn ...
A5C1D2H2I1M1N2O1R2T1
5
Was ist, wenn ich nicht zwei Variablen, sondern zwei Funktionen möchte? Zum Beispiel mean und sd.
Skan
51

Verwendung des data.tablePakets, das schnell ist (nützlich für größere Datensätze)

https://github.com/Rdatatable/data.table/wiki

library(data.table)
df2 <- setDT(df1)[, lapply(.SD, sum), by=.(year, month), .SDcols=c("x1","x2")]
setDF(df2) # convert back to dataframe

Verwendung des Plyr-Pakets

require(plyr)
df2 <- ddply(df1, c("year", "month"), function(x) colSums(x[c("x1", "x2")]))

Verwenden von summarize () aus dem Hmisc-Paket (Spaltenüberschriften sind in meinem Beispiel jedoch unübersichtlich)

# need to detach plyr because plyr and Hmisc both have a summarize()
detach(package:plyr)
require(Hmisc)
df2 <- with(df1, summarize( cbind(x1, x2), by=llist(year, month), FUN=colSums))
Numbercruncher
quelle
Warum nicht für die Option data.table : dt[, .(x1.sum = sum(x1), x2.sum = sum(x2), by = c(year, month)?
Bulat
48

Mit dem dplyrPaket können Sie verwenden summarise_all, summarise_atoder summarise_ifFunktionen mehrere Variablen gleichzeitig zu aggregieren. Für den Beispieldatensatz können Sie dies wie folgt tun:

library(dplyr)
# summarising all non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_all(sum)

# summarising a specific set of non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(x1, x2), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(-date), sum)

# summarising a specific set of non-grouping variables using select_helpers
# see ?select_helpers for more options
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(starts_with('x')), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(matches('.*[0-9]')), sum)

# summarising a specific set of non-grouping variables based on condition (class)
df2 <- df1 %>% group_by(year, month) %>% summarise_if(is.numeric, sum)

Das Ergebnis der beiden letztgenannten Optionen:

    year month        x1         x2
   <dbl> <dbl>     <dbl>      <dbl>
1   2000     1 -73.58134  -92.78595
2   2000     2 -57.81334 -152.36983
3   2000     3 122.68758  153.55243
4   2000     4 450.24980  285.56374
5   2000     5 678.37867  384.42888
6   2000     6 792.68696  530.28694
7   2000     7 908.58795  452.31222
8   2000     8 710.69928  719.35225
9   2000     9 725.06079  914.93687
10  2000    10 770.60304  863.39337
# ... with 14 more rows

Hinweis: summarise_eachist für veraltet summarise_all, summarise_atund summarise_if.


Wie in meinem obigen Kommentar erwähnt , können Sie auch die recastFunktion aus dem reshape2-Paket verwenden:

library(reshape2)
recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))

das wird Ihnen das gleiche Ergebnis geben.

Jaap
quelle
8

Interessanterweise Basis R aggregate‚s data.frameist Methode nicht hier zur Schau gestellt , über die Formel - Schnittstelle verwendet wird, so der Vollständigkeit halber:

aggregate(
  x = df1[c("x1", "x2")],
  by = df1[c("year", "month")],
  FUN = sum, na.rm = TRUE
)

Allgemeinere Verwendung der data.frame-Methode des Aggregats:

Da bieten wir eine

  • data.frameals xund
  • a list( data.frameist auch a list) alsby , dies ist sehr nützlich, wenn wir es dynamisch verwenden müssen, z. B. ist die Verwendung anderer Spalten, die aggregiert und aggregiert werden sollen, sehr einfach
  • auch mit maßgeschneiderten Aggregationsfunktionen

Zum Beispiel so:

colsToAggregate <- c("x1")
aggregateBy <- c("year", "month")
dummyaggfun <- function(v, na.rm = TRUE) {
  c(sum = sum(v, na.rm = na.rm), mean = mean(v, na.rm = na.rm))
}

aggregate(df1[colsToAggregate], by = df1[aggregateBy], FUN = dummyaggfun)
Jozef
quelle
1

Weitere Informationen zu einer flexibleren und schnelleren Vorgehensweise bei der Datenaggregation finden Sie in der collapFunktion im auf CRAN verfügbaren Collapse R-Paket:

library(collapse)
# Simple aggregation with one function
head(collap(df1, x1 + x2 ~ year + month, fmean))

  year month        x1        x2
1 2000     1 -1.217984  4.008534
2 2000     2 -1.117777 11.460301
3 2000     3  5.552706  8.621904
4 2000     4  4.238889 22.382953
5 2000     5  3.124566 39.982799
6 2000     6 -1.415203 48.252283

# Customized: Aggregate columns with different functions
head(collap(df1, x1 + x2 ~ year + month, 
      custom = list(fmean = c("x1", "x2"), fmedian = "x2")))

  year month  fmean.x1  fmean.x2 fmedian.x2
1 2000     1 -1.217984  4.008534   3.266968
2 2000     2 -1.117777 11.460301  11.563387
3 2000     3  5.552706  8.621904   8.506329
4 2000     4  4.238889 22.382953  20.796205
5 2000     5  3.124566 39.982799  39.919145
6 2000     6 -1.415203 48.252283  48.653926

# You can also apply multiple functions to all columns
head(collap(df1, x1 + x2 ~ year + month, list(fmean, fmin, fmax)))

  year month  fmean.x1    fmin.x1  fmax.x1  fmean.x2   fmin.x2  fmax.x2
1 2000     1 -1.217984 -4.2460775 1.245649  4.008534 -1.720181 10.47825
2 2000     2 -1.117777 -5.0081858 3.330872 11.460301  9.111287 13.86184
3 2000     3  5.552706  0.1193369 9.464760  8.621904  6.807443 11.54485
4 2000     4  4.238889  0.8723805 8.627637 22.382953 11.515753 31.66365
5 2000     5  3.124566 -1.5985090 7.341478 39.982799 31.957653 46.13732
6 2000     6 -1.415203 -4.6072295 2.655084 48.252283 42.809211 52.31309

# When you do that, you can also return the data in a long format
head(collap(df1, x1 + x2 ~ year + month, list(fmean, fmin, fmax), return = "long"))

  Function year month        x1        x2
1    fmean 2000     1 -1.217984  4.008534
2    fmean 2000     2 -1.117777 11.460301
3    fmean 2000     3  5.552706  8.621904
4    fmean 2000     4  4.238889 22.382953
5    fmean 2000     5  3.124566 39.982799
6    fmean 2000     6 -1.415203 48.252283

Hinweis : Sie können Basisfunktionen wie mean, maxusw. mit verwenden collap, aber fmean, fmaxusw. sind C ++ - basierte gruppierte Funktionen, die im Collapse- Paket angeboten werden und erheblich schneller sind (dh die Leistung bei großen Datenaggregationen entspricht der von data.table und bietet gleichzeitig mehr Flexibilität und) Diese schnell gruppierten Funktionen können auch ohne verwendet werdencollap .

Hinweis 2 : collapUnterstützt auch die flexible Multitype-Datenaggregation, die Sie natürlich mit dem customArgument durchführen können, aber Sie können Funktionen auch halbautomatisch auf numerische und nicht numerische Spalten anwenden:

# wlddev is a data set of World Bank Indicators provided in the collapse package
head(wlddev)

      country iso3c       date year decade     region     income  OECD PCGDP LIFEEX GINI       ODA
1 Afghanistan   AFG 1961-01-01 1960   1960 South Asia Low income FALSE    NA 32.292   NA 114440000
2 Afghanistan   AFG 1962-01-01 1961   1960 South Asia Low income FALSE    NA 32.742   NA 233350000
3 Afghanistan   AFG 1963-01-01 1962   1960 South Asia Low income FALSE    NA 33.185   NA 114880000
4 Afghanistan   AFG 1964-01-01 1963   1960 South Asia Low income FALSE    NA 33.624   NA 236450000
5 Afghanistan   AFG 1965-01-01 1964   1960 South Asia Low income FALSE    NA 34.060   NA 302480000
6 Afghanistan   AFG 1966-01-01 1965   1960 South Asia Low income FALSE    NA 34.495   NA 370250000

# This aggregates the data, applying the mean to numeric and the statistical mode to categorical columns
head(collap(wlddev, ~ iso3c + decade, FUN = fmean, catFUN = fmode))

  country iso3c       date   year decade                     region      income  OECD    PCGDP   LIFEEX GINI      ODA
1   Aruba   ABW 1961-01-01 1962.5   1960 Latin America & Caribbean  High income FALSE       NA 66.58583   NA       NA
2   Aruba   ABW 1967-01-01 1970.0   1970 Latin America & Caribbean  High income FALSE       NA 69.14178   NA       NA
3   Aruba   ABW 1976-01-01 1980.0   1980 Latin America & Caribbean  High income FALSE       NA 72.17600   NA 33630000
4   Aruba   ABW 1987-01-01 1990.0   1990 Latin America & Caribbean  High income FALSE 23677.09 73.45356   NA 41563333
5   Aruba   ABW 1996-01-01 2000.0   2000 Latin America & Caribbean  High income FALSE 26766.93 73.85773   NA 19857000
6   Aruba   ABW 2007-01-01 2010.0   2010 Latin America & Caribbean  High income FALSE 25238.80 75.01078   NA       NA

# Note that by default (argument keep.col.order = TRUE) the column order is also preserved
Sebastian
quelle
0

Spät zur Party, aber vor kurzem einen anderen Weg gefunden, um die zusammenfassende Statistik zu bekommen.

library(psych) describe(data)

Gibt aus: Mittelwert, Min, Max, Standardabweichung, n, Standardfehler, Kurtosis, Schiefe, Median und Bereich für jede Variable.

britt
quelle
Die Frage ist über Aggregationen nach Gruppe , describemacht aber nichts nach Gruppe ...
Gregor Thomas
describe.by(column, group = grouped_column)wird die Werte
gruppieren
4
Nun, setzen Sie das in die Antwort dann! Verstecke es nicht in einem Kommentar!
Gregor Thomas
0

Mit der develVersion von dplyr(version - ‘0.8.99.9000’) können wir auch summariseFunktionen auf mehrere Spalten mit anwendenacross

library(dplyr)
df1 %>% 
    group_by(year, month) %>%
    summarise(across(starts_with('x'), sum))
# A tibble: 24 x 4
# Groups:   year [2]
#    year month     x1     x2
#   <dbl> <dbl>  <dbl>  <dbl>
# 1  2000     1   11.7  52.9 
# 2  2000     2  -74.1 126.  
# 3  2000     3 -132.  149.  
# 4  2000     4 -130.    4.12
# 5  2000     5  -91.6 -55.9 
# 6  2000     6  179.   73.7 
# 7  2000     7   95.0 409.  
# 8  2000     8  255.  283.  
# 9  2000     9  489.  331.  
#10  2000    10  719.  305.  
# … with 14 more rows
akrun
quelle