นับจำนวนแถวในแต่ละกลุ่ม


121

ฉันมี dataframe และฉันต้องการนับจำนวนแถวในแต่ละกลุ่ม ฉันใช้aggregateฟังก์ชันเพื่อสรุปข้อมูลดังต่อไปนี้:

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

ตอนนี้ผมอยากจะนับข้อสังเกต FUNแต่ไม่สามารถดูเหมือนจะหาข้อโต้แย้งที่เหมาะสมสำหรับ โดยสัญชาตญาณฉันคิดว่ามันจะเป็นดังนี้:

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

แต่โชคไม่ดี

ความคิดใด ๆ ?


ข้อมูลของเล่นบางส่วน:

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...
โจชัวอูล

15
ฉันอ่านคำถามนี้ไปเรื่อย ๆ เพื่อขอวิธีนับสิ่งต่าง ๆ อย่างสนุกสนาน (ซึ่งตรงข้ามกับวิธีที่ไม่สนุกมากมายฉันเดา)
Hong Ooi

6
@JoshuaUlrich: nrowไม่ได้ทำงานสำหรับฉัน แต่NROWและlengthทำงานได้ดี +1
Prolix

คำตอบ:


69

แนวทางปฏิบัติที่ดีที่สุดในปัจจุบัน (tidyverse) คือ:

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

มีวิธีการรวมตัวแปรและทำการนับด้วยหรือไม่ (เช่น 2 ฟังก์ชันในการรวม: mean + count) ฉันต้องการหาค่าเฉลี่ยของคอลัมน์และจำนวนแถวสำหรับค่าเดียวกันในคอลัมน์อื่น
สบ

1
ฉันได้cbindผลลัพธ์aggregate(Sepal.Length ~ Species, iris, mean)และaggregate(Sepal.Length ~ Species, iris, length)
geotheory

ฉันทำไปแล้ว แต่ดูเหมือนว่าจะได้ 2 ครั้งในแต่ละคอลัมน์ยกเว้นคอลัมน์ที่รวม ดังนั้นฉันจึงทำการรวมกับพวกเขาและดูเหมือนว่าจะโอเค
สบ

6
ฉันไม่รู้ แต่สิ่งนี้อาจมีประโยชน์เช่นกัน ...df %>% group_by(group, variable) %>% mutate(count = n())
มาโนชกุมาร

1
ใช่ dplyr เป็นแนวทางปฏิบัติที่ดีที่สุดในตอนนี้
geotheory

67

ทำตามคำแนะนำของ @ Joshua ต่อไปนี้เป็นวิธีหนึ่งที่คุณอาจนับจำนวนการสังเกตในdfกรอบข้อมูลของคุณโดยที่Year= 2007 และMonth= พ.ย. (สมมติว่าเป็นคอลัมน์):

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

และตามด้วยaggregate@GregSnow:

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

47

dplyrแพคเกจทำสิ่งนี้ด้วยcount/ tallyคำสั่งหรือn()ฟังก์ชัน :

ขั้นแรกข้อมูลบางส่วน:

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

ตอนนี้นับ:

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

นอกจากนี้เรายังสามารถใช้เวอร์ชันที่ยาวกว่าเล็กน้อยด้วยการวางท่อและn()ฟังก์ชัน:

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

หรือtallyฟังก์ชัน:

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

37

คำถามเก่าที่ไม่มีทางdata.tableแก้ไข ต่อไปนี้ ...

การใช้ .N

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

1
มาตรฐานในปัจจุบันใช้.()แทนlist()และsetDT()แปลง data.frame เป็น data.table ในขั้นตอนsetDT(df)[, .N, by = .(year, month)]เดียว
sindri_baldur

23

ตัวเลือกที่ง่ายต่อการใช้กับaggregateเป็นlengthฟังก์ชั่นที่จะทำให้คุณมีความยาวของเวกเตอร์ในเซต บางครั้งเล็ก ๆ น้อย ๆ function(x) sum( !is.na(x) )ที่มีประสิทธิภาพมากขึ้นคือการใช้งาน


18

สร้างตัวแปรใหม่Countโดยมีค่า 1 สำหรับแต่ละแถว:

df1["Count"] <-1

จากนั้นรวมดาต้าเฟรมโดยสรุปด้วยCountคอลัมน์:

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

โปรดทราบว่าหากคุณใช้ค่าเริ่มต้นวิธีที่ไม่ใช่สูตรสำหรับaggregateคุณไม่จำเป็นต้องเปลี่ยนชื่อตัวแปรแต่ละตัวในby=ลักษณะlist(year=df1$year)อื่น ๆ A data.frameเป็นค่าlistเริ่มต้นแล้วจึงaggregate(df1[c("Count")], by=df1[c("Year", "Month")], FUN=sum, na.rm=TRUE)จะใช้งานได้
thelatemail

17

อีกทางเลือกหนึ่งของaggregate()ฟังก์ชันในกรณีนี้จะเป็นtable()ด้วยas.data.frame()ซึ่งจะระบุด้วยว่าชุดค่าผสมของปีและเดือนใดที่เกี่ยวข้องกับการเกิดศูนย์

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

และไม่มีชุดค่าผสมที่เกิดขึ้นเป็นศูนย์

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

7

หากคุณต้องการรวมการนับ 0 สำหรับเดือน - ปีที่ขาดหายไปในข้อมูลคุณสามารถใช้tableเวทมนตร์เล็กน้อย

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

ตัวอย่างเช่น toy data.frame ในคำถาม df1 ไม่มีข้อสังเกตของเดือนมกราคม 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

aggregateฟังก์ชันR ฐานไม่ส่งคืนการสังเกตของเดือนมกราคม 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

หากคุณต้องการให้การสังเกตของเดือน - ปีนี้เป็นจำนวนนับรหัสด้านบนจะส่งคืน data.frame พร้อมการนับสำหรับการรวมเดือน - ปีทั้งหมด:

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

สำหรับการรวมตัวของฉันฉันมักต้องการดูค่าเฉลี่ยและ "กลุ่มนี้ใหญ่แค่ไหน" (aka length) นี่คือตัวอย่างข้อมูลที่มีประโยชน์สำหรับโอกาสเหล่านั้น

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)

5

วิธีแก้ปัญหาโดยใช้sqldfแพ็คเกจ:

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

1

เมื่อพิจารณาคำตอบ @Ben R จะแสดงข้อผิดพลาดหากdf1ไม่มีxคอลัมน์ แต่สามารถแก้ไขได้อย่างสวยงามด้วยpaste:

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

ในทำนองเดียวกันสามารถสรุปได้หากใช้มากกว่าสองตัวแปรในการจัดกลุ่ม:

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

0

คุณสามารถใช้byฟังก์ชันby(df1$Year, df1$Month, count)ที่จะสร้างรายการการรวมที่จำเป็น

ผลลัพธ์จะมีลักษณะดังนี้

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

มีคำตอบที่ยอดเยี่ยมมากมายที่นี่แล้ว แต่ฉันต้องการเพิ่มอีก 1 ตัวเลือกสำหรับผู้ที่ต้องการเพิ่มคอลัมน์ใหม่ในชุดข้อมูลเดิมที่มีจำนวนครั้งที่แถวนั้นซ้ำ

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

สามารถทำได้โดยการรวมคำตอบใด ๆ ข้างต้นเข้ากับmerge()ฟังก์ชัน


0

หากคุณลองใช้วิธีแก้ปัญหาแบบรวมด้านบนและคุณได้รับข้อผิดพลาด:

ประเภทที่ไม่ถูกต้อง (รายการ) สำหรับตัวแปร

เนื่องจากคุณใช้การประทับวันที่หรือวันที่และเวลาลองใช้ as.character กับตัวแปร:

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

ตัวแปรหนึ่งหรือทั้งสองตัวแปร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.