J'ai une base de données et j'aimerais compter le nombre de lignes dans chaque groupe. J'utilise régulièrement la fonction aggregate
pour additionner les données comme suit:
df2 <- aggregate(x ~ Year + Month, data = df1, sum)
Maintenant, j'aimerais compter les observations, mais n'arrive pas à trouver le bon argument pour FUN
. Intuitivement, j'ai pensé que ce serait comme suit:
df2 <- aggregate(x ~ Year + Month, data = df1, count)
Mais pas de chance.
Des idées?
Quelques données sur les jouets:
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))
Il y a aussi df2 <- count(x, c('Year','Month'))
(paquet plyr)
En suivant la suggestion de @ Joshua, voici une façon de compter le nombre d'observations dans votre cadre de données df
où Year
= 2007 et Month
= Nov (en supposant qu'il s'agisse de colonnes):
nrow(df[,df$YEAR == 2007 & df$Month == "Nov"])
et avec aggregate
, à la suite de @GregSnow:
aggregate(x ~ Year + Month, data = df, FUN = length)
Nous pouvons également utiliser dplyr
.
Tout d'abord, quelques données:
df <- data.frame(x = rep(1:6, rep(c(1, 2, 3), 2)), year = 1993:2004, month = c(1, 1:11))
Maintenant le compte:
library(dplyr)
count(df, year, month)
#piping
df %>% count(year, month)
Nous pouvons également utiliser une version légèrement plus longue avec tuyauterie et fonction n()
:
df %>%
group_by(year, month) %>%
summarise(number = n())
ou la fonction tally
:
df %>%
group_by(year, month) %>%
tally()
Une vieille question sans solution data.table
. Alors voilà ...
Utiliser .N
library(data.table)
DT <- data.table(df)
DT[, .N, by = list(year, month)]
L'option simple à utiliser avec aggregate
est la fonction length
qui vous donnera la longueur du vecteur dans le sous-ensemble. Parfois, un peu plus robuste consiste à utiliser function(x) sum( !is.na(x) )
.
Créez une nouvelle variable Count
avec une valeur de 1 pour chaque ligne:
df1["Count"] <-1
Puis agrégez la base de données en faisant la somme de la colonne Count
:
df2 <- aggregate(df1[c("Count")], by=list(year=df1$year, month=df1$month), FUN=sum, na.rm=TRUE)
Une alternative à la fonction aggregate()
dans ce cas serait table()
avec as.data.frame()
, qui indiquerait également quelles combinaisons d'année et de mois sont associées à zéro
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")]))
Et sans les combinaisons nulles
myAns[which(myAns$Freq>0),]
Si vous souhaitez inclure 0 nombre pour les mois-années manquants dans les données, vous pouvez utiliser un peu de magie table
.
data.frame(with(df1, table(Year, Month)))
Par exemple, le jouet data.frame dans la question, df1, ne contient aucune observation de janvier 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
La fonction de base R aggregate
ne renvoie pas d'observation pour janvier 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
Si vous souhaitez une observation de cette année mois avec 0 comme nombre, le code ci-dessus renvoie un nom data.frame avec des comptes pour toutes les combinaisons mois-année:
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
Pour mes agrégations, je finis généralement par vouloir voir la moyenne et "quelle est la taille de ce groupe" (longueur.k.a.) ... C'est donc mon extrait pratique pour ces occasions;
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)
Une solution sql utilisant le package sqldf
:
library(sqldf)
sqldf("SELECT Year, Month, COUNT(*) as Freq
FROM df1
GROUP BY Year, Month")
En considérant @Ben answer, R émettrait une erreur si df1
ne contient pas de colonne x
. Mais cela peut être résolu élégamment avec paste
:
aggregate(paste(Year, Month) ~ Year + Month, data = df1, FUN = NROW)
De même, il peut être généralisé si plus de deux variables sont utilisées dans le regroupement:
aggregate(paste(Year, Month, Day) ~ Year + Month + Day, data = df1, FUN = NROW)
Il y a déjà beaucoup de réponses merveilleuses ici, mais je voulais ajouter une option supplémentaire à ceux qui souhaitent ajouter une nouvelle colonne au jeu de données d'origine contenant le nombre de répétitions de cette ligne.
df1$counts <- sapply(X = paste(df1$Year, df1$Month),
FUN = function(x) { sum(paste(df1$Year, df1$Month) == x) })
La même chose pourrait être accomplie en combinant l’une des réponses ci-dessus avec la fonction merge()
.
Vous pouvez utiliser les fonctions by
en tant que by(df1$Year, df1$Month, count)
qui produira une liste des agrégations nécessaires.
La sortie ressemblera à
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
>