Himpun / rangkumlah beberapa variabel per kelompok (mis. Jumlah, rata-rata)

154

Dari data frame, apakah ada cara mudah untuk agregat ( sum, mean, maxet c) beberapa variabel secara bersamaan?

Berikut adalah beberapa contoh data:

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)

Saya ingin secara bersamaan mengumpulkan x1dan x2variabel dari df2bingkai data berdasarkan tahun dan bulan. Kode berikut mengagregasi x1variabel, tetapi apakah mungkin juga untuk secara bersamaan mengagregasi x2variabel?

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

Setiap saran akan sangat dihargai.

MikeTP
sumber

Jawaban:

45

Dari mana year()fungsi ini ?

Anda juga bisa menggunakan reshape2paket untuk tugas ini:

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
sumber
8
The recastfunction (juga dari reshape2) mengintegrasikan meltdan dcastfungsi dalam satu pergi untuk tugas-tugas seperti ini:recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))
Jaap
184

Ya, di Anda formula, Anda dapat cbindmenjumlahkan variabel numerik:

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

Lihat ?aggregate, formulaargumen dan contohnya.

Andrie
sumber
3
Apakah mungkin bagi cbind untuk menggunakan variabel dinamis?
pdb
14
Perlu dicatat bahwa ketika salah satu variabel yang ada di dalam cbind memiliki NA, baris akan dijatuhkan untuk setiap variabel di cbind. Ini bukan perilaku yang kuharapkan.
pdb
1
bagaimana jika saya bukannya x1 dan x2 Saya ingin menggunakan semua variabel yang tersisa (selain tahun, bulan)
Clock Slave
7
@ClockSlave, maka Anda hanya perlu menggunakan .pada LHS. aggregate(. ~ year + month, df1, sum, na.rm = TRUE). Dalam contoh ini, sumuntuk "date" tidak masuk akal ....
A5C1D2H2I1M1N2O1R2T1
5
Bagaimana jika saya tidak ingin dua variabel tetapi dua fungsi? Misalnya mean dan sd.
skan
51

Menggunakan data.table paket, yang cepat (berguna untuk kumpulan data yang lebih besar)

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

Menggunakan paket plyr

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

Menggunakan ringkasan () dari paket Hmisc (judul kolom berantakan pada contoh saya)

# 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))
pembuat angka
sumber
mengapa tidak melakukan ini untuk opsi data.table: dt[, .(x1.sum = sum(x1), x2.sum = sum(x2), by = c(year, month)?
Bulat
48

Dengan dplyrpaket, Anda dapat menggunakan summarise_all, summarise_atatau summarise_iffungsi untuk menggabungkan beberapa variabel secara bersamaan. Untuk dataset contoh, Anda dapat melakukan ini sebagai berikut:

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)

Hasil dari dua opsi terakhir:

    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

Catatan: summarise_eachtidak digunakan lagi untuk summarise_all, summarise_atdan summarise_if.


Seperti disebutkan dalam komentar saya di atas , Anda juga dapat menggunakan recastfungsi dari reshape2-paket:

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

yang akan memberi Anda hasil yang sama.

Jaap
sumber
8

Menariknya, basis R aggregate's data.framemetode tidak dipamerkan di sini, di atas antarmuka rumus yang digunakan, sehingga untuk kelengkapan:

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

Penggunaan metode data.frame agregat yang lebih umum:

Karena kami menyediakan a

  • data.frame sebagai x dan
  • a list( data.framejuga a list) sebagaiby , ini sangat berguna jika kita perlu menggunakannya secara dinamis, misalnya menggunakan kolom lain untuk diagregasi dan untuk diagregasi dengan sangat sederhana
  • juga dengan fungsi agregasi yang dibuat khusus

Misalnya seperti ini:

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
sumber
1

Dengan develversi dplyr(versi - ‘0.8.99.9000’), kita juga dapat menggunakan summariseuntuk menerapkan fungsi pada banyak kolom denganacross

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
sumber
1

Untuk pendekatan agregasi data yang lebih fleksibel dan lebih cepat, lihat collapfungsi dalam paket R collapse yang tersedia di CRAN:

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

Catatan : Anda dapat menggunakan fungsi-fungsi dasar seperti mean, maxdll dengan collap, tetapi fmean, fmaxdll. Adalah fungsi-fungsi yang dikelompokkan berdasarkan C ++ yang ditawarkan dalam paket runtuh yang secara signifikan lebih cepat (yaitu kinerja pada agregasi data besar sama dengan data.tabel sambil memberikan fleksibilitas yang lebih besar, dan fungsi yang dikelompokkan cepat ini juga dapat digunakan tanpa collap).

Note2 : collapjuga mendukung agregasi data multitaspe fleksibel, yang tentu saja dapat Anda lakukan menggunakan customargumen, tetapi Anda juga dapat menerapkan fungsi ke kolom numerik dan non-numerik dengan cara semi-otomatis:

# 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
sumber
0

Terlambat ke pesta, tetapi baru-baru ini menemukan cara lain untuk mendapatkan ringkasan statistik.

library(psych) describe(data)

Output akan: mean, min, maks, standar deviasi, n, standard error, kurtosis, skewness, median, dan range untuk setiap variabel.

britt
sumber
Pertanyaannya adalah tentang melakukan agregasi berdasarkan kelompok , tetapi describetidak melakukan apa pun berdasarkan kelompok ...
Gregor Thomas
describe.by(column, group = grouped_column)akan mengelompokkan nilai
britt
4
Nah, masukkan itu dalam jawabannya kalau begitu! Jangan sembunyikan di komentar!
Gregor Thomas