Đếm số hàng trong mỗi nhóm


121

Tôi có một khung dữ liệu và tôi muốn đếm số hàng trong mỗi nhóm. Tôi thường sử dụng aggregatehàm để tính tổng dữ liệu như sau:

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

Bây giờ, tôi muốn đếm các quan sát nhưng dường như không thể tìm ra đối số thích hợp cho FUN. Theo trực giác, tôi nghĩ nó sẽ như sau:

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

Nhưng, không có may mắn như vậy.

Có ý kiến ​​gì không?


Một số dữ liệu đồ chơi:

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
Tôi tiếp tục đọc câu hỏi này như yêu cầu một cách thú vị để đếm mọi thứ (trái ngược với nhiều cách chưa được áp dụng, tôi đoán vậy).
Hong Ooi

6
@JoshuaUlrich: nrowkhông hiệu quả với tôi nhưng NROWlengthhoạt động tốt. +1
Prolix

Câu trả lời:


69

Phương pháp hay nhất hiện tại (ngăn nắp) là:

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

Có cách nào để tổng hợp một biến và cũng thực hiện đếm (như 2 hàm trong tổng hợp: mean + count) không? Tôi cần lấy giá trị trung bình của một cột và số hàng cho cùng một giá trị trong cột khác
sop

1
Tôi muốn cbindkết quả của aggregate(Sepal.Length ~ Species, iris, mean)aggregate(Sepal.Length ~ Species, iris, length)
geotheory

Tôi đã làm điều đó, nhưng dường như tôi nhận được 2 lần mỗi cột trừ cột được tổng hợp; vì vậy tôi đã thực hiện hợp nhất chúng và nó có vẻ ổn
sop

6
Tôi không biết nhưng điều này cũng có thể hữu ích ...df %>% group_by(group, variable) %>% mutate(count = n())
Manoj Kumar

1
Có dplyr là thực hành tốt nhất bây giờ.
geotheory

67

Theo đề xuất của @ Joshua, đây là một cách bạn có thể đếm số lần quan sát trong dfkhung dữ liệu của mình , trong đó Year= 2007 và Month= tháng 11 (giả sử chúng là cột):

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

và với aggregate, theo dõi @GregSnow:

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

47

dplyrgói thực hiện điều này với count/ tallylệnh hoặc n()hàm :

Đầu tiên, một số dữ liệu:

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

Bây giờ đếm:

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

Chúng tôi cũng có thể sử dụng phiên bản dài hơn một chút với đường ống và n()chức năng:

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

hoặc tallyhàm:

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

37

Một câu hỏi cũ mà không có lời data.tablegiải. Vì vậy, đây là ...

Sử dụng .N

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

1
tiêu chuẩn ngày nay để sử dụng .()thay vì list()setDT()chuyển đổi data.frame thành data.table. Vì vậy, trong một bước setDT(df)[, .N, by = .(year, month)].
sindri_baldur 27/09/19

23

Tùy chọn đơn giản để sử dụng aggregatelengthhàm sẽ cung cấp cho bạn độ dài của vectơ trong tập hợp con. Đôi khi mạnh mẽ hơn một chút là sử dụng function(x) sum( !is.na(x) ).


18

Tạo một biến mới Countvới giá trị 1 cho mỗi hàng:

df1["Count"] <-1

Sau đó tổng hợp khung dữ liệu, tổng hợp theo Countcột:

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

Chỉ cần lưu ý rằng nếu bạn đang sử dụng phương thức mặc định, không có công thức cho aggregate, thì không cần phải đổi tên từng biến thành by=như list(year=df1$year)v.v ... A data.framelà một listđã có nên aggregate(df1[c("Count")], by=df1[c("Year", "Month")], FUN=sum, na.rm=TRUE)sẽ hoạt động.
thelatemail

17

Một thay thế cho aggregate()hàm trong trường hợp này sẽ là table()với as.data.frame(), cũng sẽ cho biết những kết hợp Năm và Tháng nào được liên kết với không xuất hiện

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")]))

Và không có các kết hợp không xảy ra

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

7

Nếu bạn muốn bao gồm các số đếm tháng-năm bị thiếu trong dữ liệu, bạn có thể sử dụng một chút tablephép thuật.

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

Ví dụ: data.frame đồ chơi trong câu hỏi, df1, không có quan sát nào về tháng 1 năm 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

Hàm R cơ sở aggregatekhông trả về một quan sát cho tháng 1 năm 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

Nếu bạn muốn quan sát tháng-năm này với số 0 là số, thì đoạn mã trên sẽ trả về data.frame với số lượng cho tất cả các kết hợp tháng-năm:

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

Đối với các tổng hợp của tôi, tôi thường muốn xem trung bình và "nhóm này lớn như thế nào" (còn gọi là độ dài). Vì vậy, đây là đoạn mã hữu ích của tôi cho những dịp đó;

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

A giải pháp sử dụng sqldfgói:

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

1

Xem xét câu trả lời @Ben, R sẽ tạo ra một lỗi nếu df1không chứa xcột. Nhưng nó có thể được giải quyết một cách nhẹ nhàng với paste:

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

Tương tự, nó có thể được tổng quát hóa nếu nhiều hơn hai biến được sử dụng trong nhóm:

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

0

Bạn có thể sử dụng các byhàm vì by(df1$Year, df1$Month, count)điều đó sẽ tạo ra một danh sách tổng hợp cần thiết.

Đầu ra sẽ như thế nào,

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

Đã có rất nhiều câu trả lời tuyệt vời ở đây, nhưng tôi muốn đưa ra thêm 1 tùy chọn cho những người muốn thêm một cột mới vào tập dữ liệu ban đầu chứa số lần hàng đó được lặp lại.

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

Điều tương tự có thể được thực hiện bằng cách kết hợp bất kỳ câu trả lời nào ở trên với merge()hàm.


0

Nếu bạn đang thử các giải pháp tổng hợp ở trên và gặp lỗi:

loại không hợp lệ (danh sách) cho biến

Vì bạn đang sử dụng tem ngày tháng hoặc ngày giờ, hãy thử sử dụng as.character trên các biến:

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

Trên một hoặc cả hai biến.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.