Порахуйте кількість рядків у кожній групі


121

У мене є кадр даних, і я хотів би порахувати кількість рядків у кожній групі. Я регулярно використовую 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...
Джошуа Ulrich

15
Я продовжую читати це питання як прохання про цікавий спосіб підрахунку речей (на відміну від багатьох невідповідних способів, я думаю).
Hong Ooi

6
@JoshuaUlrich: nrowне працює для мене , але NROWі lengthпрацював відмінно. +1
Пролікс

Відповіді:


69

Поточна найкраща практика (tidyverse):

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

Чи є спосіб агрегувати змінну і зробити підрахунок теж (як 2 функції в агрегації: середнє + число)? Мені потрібно отримати середнє значення стовпця та кількість рядків для того ж значення в іншій колонці
sop

1
Я cbindaggregate(Sepal.Length ~ Species, iris, mean)aggregate(Sepal.Length ~ Species, iris, length)
отримав

Я це зробив, але, схоже, я отримую 2 рази в кожному стовпчику, крім того, що є агрегованим; тому я зробив злиття з ними, і, здається, все в порядку
соп

6
Я не знаю, але це також може бути корисним ...df %>% group_by(group, variable) %>% mutate(count = n())
Маной Кумар

1
Так, dplyr - найкраща практика зараз.
геотеорія

67

Слідом за пропозицією @ Джошуа, ось один із способів ви можете підрахувати кількість спостережень у вашому dfкадрі даних, де Year= 2007 та Month= Nov (якщо вважати, що вони є стовпцями):

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)тощо. А 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)))

Наприклад, іграшка 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

Якщо ви хочете спостерігати цей місяць-рік із числом 0, тоді вищевказаний код поверне дані.фрейм із підрахунками для всіх комбінацій місяця-року:

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

Для моїх агрегацій я, як правило, хочу побачити середнє значення та "наскільки велика ця група" (він же довжина). Отже, це мій зручний фрагмент для тих випадків;

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

А рішення за допомогою 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

Тут вже є безліч чудових відповідей, але я хотів запропонувати ще один варіант для тих, хто хоче додати новий стовпець до початкового набору даних, який містить кількість разів повторення цього рядка.

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)

На одній або обох змінних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.