Агрегировать / суммировать несколько переменных на группу (например, сумма, среднее) - PullRequest
135 голосов
/ 15 марта 2012

Из фрейма данных существует ли простой способ агрегирования (sum, mean, max и т. Д.) Нескольких переменных одновременно?

Ниже приведены некоторые примеры данных:

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)

Я бы хотел объединить переменные x1 и x2 из фрейма данных df2 по годам и месяцам. Следующий код агрегирует переменную x1, но возможно ли одновременно агрегировать переменную x2?

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

Любые предложения будут с благодарностью.

Ответы [ 6 ]

179 голосов
/ 15 марта 2012

Да, в вашем formula вы можете cbind числовые переменные для агрегирования:

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

См. ?aggregate, аргумент formula и примеры.

47 голосов
/ 16 марта 2012

Использование пакета data.table, что быстро (полезно для больших наборов данных)

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

Использование пакета plyr

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

Использование summaze () из пакета Hmisc (в моем примере заголовки столбцов грязные)

# 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))
44 голосов
/ 16 октября 2015

С пакетом dplyr вы можете использовать функции summarise_all, summarise_at или summarise_if для объединения нескольких переменных одновременно.Для примера набора данных вы можете сделать это следующим образом:

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)

Результат двух последних опций:

    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

Примечание: summarise_each не рекомендуется в пользу summarise_all, summarise_at и summarise_if.


Как уже упоминалось в моем комментарии выше , вы также можете использовать функцию recast из пакета reshape2:

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

, который даст вам тот же результат.

43 голосов
/ 15 марта 2012

Откуда эта year() функция?

Вы также можете использовать пакет reshape2 для этой задачи:

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
5 голосов
/ 27 декабря 2018

Интересно, что базовый метод R aggregate data.frame здесь не представлен, выше используется интерфейс формулы, поэтому для полноты:

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

Более общее использование метода data.frame агрегата:

Так как мы предоставляем

  • data.frame как x и
  • a list (data.frame также list) как by, это очень полезно, если нам нужно использовать его динамически, например, использовать другие столбцы для агрегирования и агрегирования очень просто
  • также с пользовательскими функциями агрегирования

Например, вот так:

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)
0 голосов
/ 15 августа 2018

Поздно на вечеринке, но недавно нашел другой способ получить сводную статистику.

library(psych) describe(data)

Будет выводить: среднее, минимальное, максимальное, стандартное отклонение, n, стандартная ошибка, эксцесс, асимметрия, медиана и диапазон для каждой переменной.

...