Hitung jumlah baris dalam setiap kelompok


121

Saya memiliki kerangka data dan saya ingin menghitung jumlah baris dalam setiap grup. Saya biasanya menggunakan aggregatefungsi untuk menjumlahkan data sebagai berikut:

df2 <- aggregate(x ~ Year + Month, data = df1, sum)

Sekarang, saya ingin menghitung pengamatan tetapi tidak dapat menemukan argumen yang tepat FUN. Secara intuitif, saya pikir itu akan menjadi sebagai berikut:

df2 <- aggregate(x ~ Year + Month, data = df1, count)

Tapi, tidak beruntung.

Ada ide?


Beberapa data mainan:

set.seed(2)
df1 <- data.frame(x = 1:20,
                  Year = sample(2012:2014, 20, replace = TRUE),
                  Month = sample(month.abb[1:3], 20, replace = TRUE))

17
nrow, NROW, length...
Joshua Ulrich

15
Saya terus membaca pertanyaan ini sebagai menanyakan cara yang menyenangkan untuk menghitung sesuatu (sebagai lawan dari banyak cara yang tidak benar, saya kira).
Hong Ooi

6
@JoshuaUlrich: nrowtidak bekerja untuk saya tetapi NROWdan lengthbekerja dengan baik. +1
Prolix

Jawaban:


69

Praktik terbaik saat ini (tidyverse) adalah:

require(dplyr)
df1 %>% count(Year, Month)

Apakah ada cara untuk menggabungkan variabel dan melakukan penghitungan juga (seperti 2 fungsi dalam agregasi: mean + count)? Saya perlu mendapatkan rata-rata kolom dan jumlah baris untuk nilai yang sama di kolom lain
sop

1
Saya akan cbindhasil aggregate(Sepal.Length ~ Species, iris, mean)danaggregate(Sepal.Length ~ Species, iris, length)
geotheory

Saya telah melakukannya, tetapi tampaknya saya mendapatkan 2 kali setiap kolom kecuali kolom yang digabungkan; jadi saya telah melakukan penggabungan pada mereka dan tampaknya baik
sop

6
Saya tidak tahu tapi ini bisa berguna juga ...df %>% group_by(group, variable) %>% mutate(count = n())
Manoj Kumar

1
Ya, dplyr adalah praktik terbaik sekarang.
geotheory

67

Mengikuti saran @ Joshua, berikut salah satu cara Anda dapat menghitung jumlah observasi dalam dfkerangka data Anda di mana Year= 2007 dan Month= Nov (dengan asumsi mereka adalah kolom):

nrow(df[,df$YEAR == 2007 & df$Month == "Nov"])

dan dengan aggregate, mengikuti @GregSnow:

aggregate(x ~ Year + Month, data = df, FUN = length)

47

dplyrpaket melakukan ini dengan count/ tallycommands, atau n()fungsinya :

Pertama, beberapa data:

df <- data.frame(x = rep(1:6, rep(c(1, 2, 3), 2)), year = 1993:2004, month = c(1, 1:11))

Sekarang hitungannya:

library(dplyr)
count(df, year, month)
#piping
df %>% count(year, month)

Kami juga dapat menggunakan versi yang sedikit lebih panjang dengan pemipaan dan n()fungsinya:

df %>% 
  group_by(year, month) %>%
  summarise(number = n())

atau tallyfungsinya:

df %>% 
  group_by(year, month) %>%
  tally()

37

Pertanyaan lama tanpa data.tablesolusi. Jadi begini ...

Menggunakan .N

library(data.table)
DT <- data.table(df)
DT[, .N, by = list(year, month)]

1
standar saat ini untuk digunakan .()sebagai ganti list()dan setDT()untuk mengubah data.frame menjadi data.table. Jadi dalam satu langkah setDT(df)[, .N, by = .(year, month)].
sindri_baldur

23

Opsi sederhana untuk digunakan dengan aggregateadalah lengthfungsi yang akan memberi Anda panjang vektor dalam subset. Terkadang sedikit lebih kuat untuk digunakan function(x) sum( !is.na(x) ).


18

Buat variabel baru Countdengan nilai 1 untuk setiap baris:

df1["Count"] <-1

Kemudian agregat dataframe, dijumlahkan dengan Countkolom:

df2 <- aggregate(df1[c("Count")], by=list(Year=df1$Year, Month=df1$Month), FUN=sum, na.rm=TRUE)

Hanya untuk catatan bahwa jika Anda menggunakan default, metode non-rumus untuk aggregate, tidak ada kebutuhan untuk mengubah nama masing-masing variabel dalam by=seperti list(year=df1$year)dll data.frameadalah listsudah begitu aggregate(df1[c("Count")], by=df1[c("Year", "Month")], FUN=sum, na.rm=TRUE)akan bekerja.
thelatemail

17

Alternatif untuk aggregate()fungsi dalam kasus ini adalah table()dengan as.data.frame(), yang juga akan menunjukkan kombinasi Tahun dan Bulan mana yang terkait dengan kejadian nol

df<-data.frame(x=rep(1:6,rep(c(1,2,3),2)),year=1993:2004,month=c(1,1:11))

myAns<-as.data.frame(table(df[,c("year","month")]))

Dan tanpa kombinasi yang terjadi nol

myAns[which(myAns$Freq>0),]

7

Jika Anda ingin memasukkan 0 hitungan bulan-tahun yang hilang dalam data, Anda dapat menggunakan sedikit tablekeajaiban.

data.frame(with(df1, table(Year, Month)))

Misalnya, mainan data.frame dalam pertanyaan, df1, tidak berisi observasi Januari 2014.

df1
    x Year Month
1   1 2012   Feb
2   2 2014   Feb
3   3 2013   Mar
4   4 2012   Jan
5   5 2014   Feb
6   6 2014   Feb
7   7 2012   Jan
8   8 2014   Feb
9   9 2013   Mar
10 10 2013   Jan
11 11 2013   Jan
12 12 2012   Jan
13 13 2014   Mar
14 14 2012   Mar
15 15 2013   Feb
16 16 2014   Feb
17 17 2014   Mar
18 18 2012   Jan
19 19 2013   Mar
20 20 2012   Jan

Fungsi dasar R aggregatetidak mengembalikan observasi untuk Januari 2014.

aggregate(x ~ Year + Month, data = df1, FUN = length)
  Year Month x
1 2012   Feb 1
2 2013   Feb 1
3 2014   Feb 5
4 2012   Jan 5
5 2013   Jan 2
6 2012   Mar 1
7 2013   Mar 3
8 2014   Mar 2

Jika Anda ingin pengamatan bulan-tahun ini dengan 0 sebagai hitungan, maka kode di atas akan mengembalikan data.frame dengan jumlah untuk semua kombinasi bulan-tahun:

data.frame(with(df1, table(Year, Month)))
  Year Month Freq
1 2012   Feb    1
2 2013   Feb    1
3 2014   Feb    5
4 2012   Jan    5
5 2013   Jan    2
6 2014   Jan    0
7 2012   Mar    1
8 2013   Mar    3
9 2014   Mar    2

5

Untuk kumpulan saya, saya biasanya ingin melihat arti dan "seberapa besar grup ini" (alias panjangnya). Jadi ini cuplikan praktis saya untuk kesempatan itu;

agg.mean <- aggregate(columnToMean ~ columnToAggregateOn1*columnToAggregateOn2, yourDataFrame, FUN="mean")
agg.count <- aggregate(columnToMean ~ columnToAggregateOn1*columnToAggregateOn2, yourDataFrame, FUN="length")
aggcount <- agg.count$columnToMean
agg <- cbind(aggcount, agg.mean)

4

SEBUAH solusi menggunakan sqldfpaket:

library(sqldf)
sqldf("SELECT Year, Month, COUNT(*) as Freq
       FROM df1
       GROUP BY Year, Month")

1

Mempertimbangkan jawaban @Ben, R akan membuat kesalahan jika df1tidak berisi xkolom. Tapi itu bisa diselesaikan dengan elegan dengan paste:

aggregate(paste(Year, Month) ~ Year + Month, data = df1, FUN = NROW)

Demikian pula, dapat digeneralisasikan jika lebih dari dua variabel digunakan dalam pengelompokan:

aggregate(paste(Year, Month, Day) ~ Year + Month + Day, data = df1, FUN = NROW)

0

Anda dapat menggunakan byfungsi karena by(df1$Year, df1$Month, count)itu akan menghasilkan daftar agregasi yang dibutuhkan.

Outputnya akan terlihat seperti,

df1$Month: Feb
     x freq
1 2012    1
2 2013    1
3 2014    5
--------------------------------------------------------------- 
df1$Month: Jan
     x freq
1 2012    5
2 2013    2
--------------------------------------------------------------- 
df1$Month: Mar
     x freq
1 2012    1
2 2013    3
3 2014    2
> 

0

Sudah ada banyak jawaban bagus di sini, tetapi saya ingin menambahkan 1 opsi lagi bagi mereka yang ingin menambahkan kolom baru ke kumpulan data asli yang berisi berapa kali baris tersebut diulang.

df1$counts <- sapply(X = paste(df1$Year, df1$Month), 
                     FUN = function(x) { sum(paste(df1$Year, df1$Month) == x) })

Hal yang sama dapat dicapai dengan menggabungkan salah satu jawaban di atas dengan merge()fungsi.


0

Jika Anda mencoba solusi agregat di atas dan Anda mendapatkan kesalahan:

jenis tidak valid (daftar) untuk variabel

Karena Anda menggunakan stempel tanggal atau waktu, coba gunakan as.character pada variabel:

aggregate(x ~ as.character(Year) + Month, data = df, FUN = length)

Pada satu atau kedua variabel.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.