1091 votes

Les fonctions de regroupement (tapply, by, aggregate) et la famille *apply

Lorsque je veux faire quelque chose de "map "py dans R, j'essaie généralement d'utiliser une fonction dans le répertoire apply famille.

Cependant, je n'ai jamais vraiment compris les différences entre les deux comment ? sapply , lapply appliquent la fonction à l'entrée ou à l'entrée groupée, à ce à quoi ressemblera la sortie, ou même à ce que peut être l'entrée - je les passe souvent en revue jusqu'à ce que j'obtienne ce que je veux.

Quelqu'un peut-il expliquer comment utiliser lequel et quand ?

Ma compréhension actuelle (probablement incorrecte/incomplète) est la suivante...

  1. sapply(vec, f) : l'entrée est un vecteur. la sortie est un vecteur/matrice, où l'élément i es f(vec[i]) en vous donnant une matrice si f a une sortie multi-éléments

  2. lapply(vec, f) : même chose que sapply mais la sortie est une liste ?

  3. apply(matrix, 1/2, f) : l'entrée est une matrice. la sortie est un vecteur, où l'élément i est f(ligne/col i de la matrice)

  4. tapply(vector, grouping, f) La sortie est une matrice/réseau, où un élément de la matrice/réseau est la valeur de f à un regroupement g du vecteur, et g est poussé vers les noms de ligne/col

  5. by(dataframe, grouping, f) : laisser g être un groupement. appliquer f à chaque colonne du groupe ou du cadre de données. Le regroupement et la valeur de la variable f à chaque colonne.

  6. aggregate(matrix, grouping, f) : similaire à by mais au lieu d'imprimer la sortie, l'agrégat place tout dans un cadre de données.

Question secondaire : Je n'ai toujours pas appris le plyr ou le reshape -- est-ce que plyr o reshape remplacer entièrement tous ces éléments ?

35 votes

À votre question secondaire : pour beaucoup de choses, plyr est un remplacement direct de *apply() y by . plyr (du moins pour moi) semble beaucoup plus cohérent dans la mesure où je sais toujours exactement quel format de données il attend et exactement ce qu'il va cracher. Cela m'évite bien des tracas.

14 votes

Aussi, je recommanderais d'ajouter : doBy et les capacités de sélection et d'application de data.table .

8 votes

sapply est juste lapply avec l'ajout de simplify2array sur la sortie. apply se transforme en vecteur atomique, mais la sortie peut être un vecteur ou une liste. by divise les cadres de données en sous-cadres de données, mais n'utilise pas la fonction f sur les colonnes séparément. Seulement s'il y a une méthode pour la classe 'data.frame'. f sont appliqués en colonne par by . aggregate est générique, de sorte que différentes méthodes existent pour différentes classes du premier argument.

1383voto

joran Points 68079

R possède de nombreuses fonctions *apply qui sont habilement décrites dans les fichiers d'aide (par ex. ?apply ). Elles sont cependant suffisamment nombreuses pour que les utilisateurs débutants aient du mal à déterminer celle qui convient à leur situation ou même à se les rappeler toutes. Ils peuvent avoir le sentiment général que "je devrais utiliser une fonction *apply ici", mais il peut être difficile de s'en souvenir au début.

Malgré le fait (noté dans d'autres réponses) qu'une grande partie de la fonctionnalité de la famille *apply est couverte par la très populaire application plyr mais les fonctions de base restent utiles et méritent d'être connues.

Cette réponse est destinée à agir comme une sorte de panneau de signalisation pour les nouveaux utilisateurs afin de les orienter vers la fonction d'application correcte pour leur problème particulier. Notez que c'est no n'a pas pour but de simplement régurgiter ou remplacer la documentation de R ! L'espoir est que cette réponse vous aide à décider quelle fonction *apply convient à votre situation et qu'il vous appartient ensuite d'approfondir vos recherches. À une exception près, les différences de performances ne seront pas abordées.

  • appliquer - Lorsque vous souhaitez appliquer une fonction aux lignes ou aux colonnes d'une matrice (et des analogues de dimensions supérieures) ; ce n'est généralement pas conseillé pour les cadres de données, car la fonction sera d'abord convertie en matrice.

     # Two dimensional matrix
     M <- matrix(seq(1,16), 4, 4)
    
     # apply min to rows
     apply(M, 1, min)
     [1] 1 2 3 4
    
     # apply max to columns
     apply(M, 2, max)
     [1]  4  8 12 16
    
     # 3 dimensional array
     M <- array( seq(32), dim = c(4,4,2))
    
     # Apply sum across each M[*, , ] - i.e Sum across 2nd and 3rd dimension
     apply(M, 1, sum)
     # Result is one-dimensional
     [1] 120 128 136 144
    
     # Apply sum across each M[*, *, ] - i.e Sum across 3rd dimension
     apply(M, c(1,2), sum)
     # Result is two-dimensional
          [,1] [,2] [,3] [,4]
     [1,]   18   26   34   42
     [2,]   20   28   36   44
     [3,]   22   30   38   46
     [4,]   24   32   40   48

    Si vous souhaitez obtenir des moyennes ou des sommes ligne/colonne pour une matrice 2D, n'hésitez pas à d'étudier le logiciel hautement optimisé et rapide comme l'éclair colMeans , rowMeans , colSums , rowSums .

  • paresseux - Lorsque vous souhaitez appliquer une fonction à chaque élément d'une liste à tour de rôle et obtenir une liste en retour.

    C'est le cheval de bataille de nombreuses autres fonctions *apply. Epluchez leur code et vous trouverez souvent lapply en dessous.

     x <- list(a = 1, b = 1:3, c = 10:100) 
     lapply(x, FUN = length) 
     $a 
     [1] 1
     $b 
     [1] 3
     $c 
     [1] 91
     lapply(x, FUN = sum) 
     $a 
     [1] 1
     $b 
     [1] 6
     $c 
     [1] 5005
  • saphir - Lorsque vous souhaitez appliquer une fonction à chaque élément d'une liste mais que vous voulez un vecteur plutôt qu'une liste.

    Si vous vous retrouvez à taper unlist(lapply(...)) arrêtez-vous et considérez sapply .

     x <- list(a = 1, b = 1:3, c = 10:100)
     # Compare with above; a named vector, not a list 
     sapply(x, FUN = length)  
     a  b  c   
     1  3 91
    
     sapply(x, FUN = sum)   
     a    b    c    
     1    6 5005 

    Dans les utilisations plus avancées de sapply il tentera de contraindre le résultat résultat dans un tableau multidimensionnel, si nécessaire. Par exemple, si notre fonction renvoie des vecteurs de même longueur, sapply les utilisera comme colonnes d'une matrice :

     sapply(1:5,function(x) rnorm(3,x))

    Si notre fonction renvoie une matrice à 2 dimensions, sapply fera essentiellement la même chose, en traitant chaque matrice retournée comme un seul long vecteur :

     sapply(1:5,function(x) matrix(x,2,2))

    A moins que nous ne spécifions simplify = "array" dans ce cas, il utilisera les matrices individuelles pour construire un tableau multidimensionnel :

     sapply(1:5,function(x) matrix(x,2,2), simplify = "array")

    Chacun de ces comportements est bien sûr subordonné au fait que notre fonction renvoie des vecteurs ou des matrices de même longueur ou dimension.

  • vapply - Lorsque vous voulez utiliser sapply mais peut-être avez-vous besoin de d'accélérer votre code ou de le rendre plus rapide. veulent plus de sécurité de type .

    Pour vapply vous donnez à R un exemple de ce que votre fonction va retourner. votre fonction retournera, ce qui peut vous faire gagner du temps pour faire pour qu'elles tiennent dans un seul vecteur atomique.

     x <- list(a = 1, b = 1:3, c = 10:100)
     #Note that since the advantage here is mainly speed, this
     # example is only for illustration. We're telling R that
     # everything returned by length() should be an integer of 
     # length 1. 
     vapply(x, FUN = length, FUN.VALUE = 0L) 
     a  b  c  
     1  3 91
  • mapply - Lorsque vous avez plusieurs structures de données (par ex. vecteurs, listes) et que vous voulez appliquer une fonction aux premiers éléments de chacune d'elles, puis aux seconds éléments de chacune d'elles, etc. de chacune d'elles, puis aux deuxièmes éléments de chacune d'elles, etc. à un vecteur/réseau comme dans sapply .

    Ceci est multivariable dans le sens où votre fonction doit accepter plusieurs arguments.

     #Sums the 1st elements, the 2nd elements, etc. 
     mapply(sum, 1:5, 1:5, 1:5) 
     [1]  3  6  9 12 15
     #To do rep(1,4), rep(2,3), etc.
     mapply(rep, 1:4, 4:1)   
     [[1]]
     [1] 1 1 1 1
    
     [[2]]
     [1] 2 2 2
    
     [[3]]
     [1] 3 3
    
     [[4]]
     [1] 4
  • Carte - Une enveloppe pour mapply con SIMPLIFY = FALSE Il est donc garanti qu'il retournera une liste.

     Map(sum, 1:5, 1:5, 1:5)
     [[1]]
     [1] 3
    
     [[2]]
     [1] 6
    
     [[3]]
     [1] 9
    
     [[4]]
     [1] 12
    
     [[5]]
     [1] 15
  • rapply - Lorsque vous souhaitez appliquer une fonction à chaque élément d'un fichier liste imbriquée structure, de manière récursive.

    Pour vous donner une idée de combien peu commun rapply c'est que j'ai oublié quand j'ai posté cette réponse ! Évidemment, je suis sûr que beaucoup de gens l'utilisent, mais c'est une question de jugement. rapply est mieux illustré avec une fonction définie par l'utilisateur à appliquer :

     # Append ! to string, otherwise increment
     myFun <- function(x){
         if(is.character(x)){
           return(paste(x,"!",sep=""))
         }
         else{
           return(x + 1)
         }
     }
    
     #A nested list structure
     l <- list(a = list(a1 = "Boo", b1 = 2, c1 = "Eeek"), 
               b = 3, c = "Yikes", 
               d = list(a2 = 1, b2 = list(a3 = "Hey", b3 = 5)))
    
     # Result is named vector, coerced to character          
     rapply(l, myFun)
    
     # Result is a nested list like l, with values altered
     rapply(l, myFun, how="replace")
  • tapply - Lorsque vous voulez appliquer une fonction à sous-ensembles d'un vecteur et les sous-ensembles sont définis par un autre vecteur, généralement un facteur.

    Le mouton noir de la famille *apply, en quelque sorte. L'utilisation dans le fichier d'aide de l'expression "ragged array" peut être un peu déroutant mais c'est en fait assez simple.

    Un vecteur :

     x <- 1:20

    Un facteur (de même longueur !) définissant les groupes :

     y <- factor(rep(letters[1:5], each = 4))

    Additionnez les valeurs dans x dans chaque sous-groupe défini par y :

     tapply(x, y, sum)  
      a  b  c  d  e  
     10 26 42 58 74 

    Des exemples plus complexes peuvent être traités lorsque les sous-groupes sont définis par les combinaisons uniques d'une liste de plusieurs facteurs. par les combinaisons uniques d'une liste de plusieurs facteurs. tapply est similaire dans l'esprit aux fonctions diviser-appliquer-combiner qui sont communes dans R ( aggregate , by , ave , ddply etc.) D'où son statut de mouton noir.

34 votes

Croyez que vous trouverez que by est un pur split-lapply et aggregate es tapply en leur cœur. Je pense que les moutons noirs font un excellent tissu.

23 votes

Une réponse fantastique ! Elle devrait faire partie de la documentation officielle de R :). Une petite suggestion : peut-être ajouter quelques puces sur l'utilisation de aggregate y by également ? (J'ai fini par les comprendre après votre description !, mais elles sont assez courantes, il pourrait être utile de les séparer et d'avoir des exemples spécifiques pour ces deux fonctions).

4 votes

@grautur J'ai activement élagué des choses de cette réponse pour éviter qu'elle soit (a) trop longue et (b) une réécriture de la documentation. J'ai décidé que pendant que aggregate , by sont basées sur des fonctions *applicatives, la façon dont vous les utilisez est suffisamment différente du point de vue des utilisateurs pour qu'elles soient résumées dans une réponse séparée. J'essaierai peut-être de le faire si j'ai le temps, ou peut-être que quelqu'un d'autre me battra et gagnera mon vote positif.

199voto

JoFrhwld Points 4142

En passant, voici comment les différents programmes de l'UE ont été conçus. plyr correspondent à la base *apply fonctions (du document d'introduction au plyr de la page web du plyr) http://had.co.nz/plyr/ )

Base function   Input   Output   plyr function 
---------------------------------------
aggregate        d       d       ddply + colwise 
apply            a       a/l     aaply / alply 
by               d       l       dlply 
lapply           l       l       llply  
mapply           a       a/l     maply / mlply 
replicate        r       a/l     raply / rlply 
sapply           l       a       laply 

L'un des objectifs de plyr consiste à fournir des conventions de dénomination cohérentes pour chacune des fonctions, en codant les types de données d'entrée et de sortie dans le nom de la fonction. Cela permet également d'assurer la cohérence de la sortie, dans la mesure où la sortie de la fonction dlply() est facilement transmissible à ldply() pour produire un résultat utile, etc.

Sur le plan conceptuel, l'apprentissage plyr n'est pas plus difficile que de comprendre la base *apply fonctions.

plyr y reshape ont remplacé presque toutes ces fonctions dans mon utilisation quotidienne. Mais, également à partir du document Intro to Plyr :

Fonctions connexes tapply y sweep n'ont pas de fonction correspondante dans plyr et restent utiles. merge est utile pour combiner les résumés avec les données originales.

14 votes

Lorsque j'ai commencé à apprendre R à partir de zéro, j'ai trouvé plyr BEAUCOUP plus facile à apprendre que le programme *apply() famille de fonctions. Pour moi, ddply() était très intuitif car je connaissais les fonctions d'agrégation SQL. ddply() est devenu mon marteau pour résoudre de nombreux problèmes, dont certains auraient pu être mieux résolus avec d'autres commandes.

1 votes

Je suppose que je me suis dit que le concept derrière plyr est similaire à *apply fonctions, donc si vous pouvez faire l'une, vous pouvez faire l'autre, mais plyr sont plus faciles à mémoriser. Mais je suis tout à fait d'accord sur le ddply() marteau !

1 votes

Le paquet plyr a le join() qui effectue des tâches similaires à celles de merge. Il est peut-être plus pertinent de la mentionner dans le contexte de plyr.

139voto

isomorphismes Points 1902

De la diapositive 21 de http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy :

apply, sapply, lapply, by, aggregate

(J'espère qu'il est clair que apply correspond à celui de @Hadley aaply y aggregate correspond à celui de @Hadley ddply etc. La diapositive 20 du même slideshare vous éclairera si vous ne comprenez pas cette image).

(à gauche l'entrée, en haut la sortie)

5 votes

Y a-t-il une faute de frappe dans la diapositive ? La cellule en haut à gauche devrait être aaply

106voto

Assad Ebrahim Points 1295

Commencez par L'excellente réponse de Joran -- Je doute que quelque chose puisse faire mieux que ça.

Les moyens mnémotechniques suivants peuvent alors vous aider à vous souvenir des distinctions entre chacun d'eux. Si certaines sont évidentes, d'autres peuvent l'être moins --- pour celles-ci, vous trouverez une justification dans les discussions de Joran.

Mnémoniques

  • lapply es un liste apply qui agit sur une liste ou un vecteur et retourne une liste.
  • sapply es un simple lapply (la fonction retourne par défaut un vecteur ou une matrice lorsque cela est possible)
  • vapply es un application vérifiée (permet de préspécifier le type d'objet de retour)
  • rapply es un récursif s'appliquent aux listes imbriquées, c'est-à-dire aux listes dans des listes
  • tapply es un Étiqueté s'appliquent où les étiquettes identifient les sous-ensembles
  • apply est Générique : applique une fonction aux lignes ou colonnes d'une matrice (ou, plus généralement, aux dimensions d'un tableau)

Créer le bon contexte

Si vous utilisez le apply Si la famille vous semble encore un peu étrangère, c'est peut-être que vous manquez un point de vue essentiel.

Ces deux articles peuvent vous aider. Ils fournissent le contexte nécessaire pour motiver les techniques de programmation fonctionnelle qui sont fournis par le apply famille de fonctions.

Les utilisateurs de Lisp reconnaîtront immédiatement ce paradigme. Si vous n'êtes pas familier avec Lisp, une fois que vous vous serez familiarisé avec FP, vous aurez acquis un point de vue puissant pour l'utiliser dans R -- et apply aura beaucoup plus de sens.

55voto

SabDeM Points 5667

Depuis que j'ai réalisé que les (très excellentes) réponses de ce post manquent de by y aggregate explications. Voici ma contribution.

PAR

El by comme indiqué dans la documentation, peut être considérée comme une "enveloppe" de la fonction tapply . Le pouvoir de by se présente lorsque nous voulons calculer une tâche qui tapply ne peut pas gérer. Un exemple est ce code :

ct <- tapply(iris$Sepal.Width , iris$Species , summary )
cb <- by(iris$Sepal.Width , iris$Species , summary )

 cb
iris$Species: setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 
-------------------------------------------------------------- 
iris$Species: versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 
-------------------------------------------------------------- 
iris$Species: virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 

ct
$setosa
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.300   3.200   3.400   3.428   3.675   4.400 

$versicolor
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.000   2.525   2.800   2.770   3.000   3.400 

$virginica
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.200   2.800   3.000   2.974   3.175   3.800 

Si nous imprimons ces deux objets, ct y cb nous obtenons "essentiellement" les mêmes résultats et les seules différences résident dans la manière dont ils sont présentés et dans les différentes méthodes de calcul. class attributs, respectivement by para cb y array para ct .

Comme je l'ai dit, le pouvoir de by survient lorsque nous ne pouvons pas utiliser tapply ; le code suivant en est un exemple :

 tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) : 
  arguments must have same length

R dit que les arguments doivent avoir les mêmes longueurs, disons "nous voulons calculer le summary de toutes les variables dans iris le long du facteur Species " : mais R ne peut pas le faire car il ne sait pas comment gérer.

Avec le by R distribue une méthode spécifique pour data frame puis laisser la classe summary fonctionne même si la longueur du premier argument (et le type aussi) sont différents.

bywork <- by(iris, iris$Species, summary )

bywork
iris$Species: setosa
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.300   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:4.800   1st Qu.:3.200   1st Qu.:1.400   1st Qu.:0.200   versicolor: 0  
 Median :5.000   Median :3.400   Median :1.500   Median :0.200   virginica : 0  
 Mean   :5.006   Mean   :3.428   Mean   :1.462   Mean   :0.246                  
 3rd Qu.:5.200   3rd Qu.:3.675   3rd Qu.:1.575   3rd Qu.:0.300                  
 Max.   :5.800   Max.   :4.400   Max.   :1.900   Max.   :0.600                  
-------------------------------------------------------------- 
iris$Species: versicolor
  Sepal.Length    Sepal.Width     Petal.Length   Petal.Width          Species  
 Min.   :4.900   Min.   :2.000   Min.   :3.00   Min.   :1.000   setosa    : 0  
 1st Qu.:5.600   1st Qu.:2.525   1st Qu.:4.00   1st Qu.:1.200   versicolor:50  
 Median :5.900   Median :2.800   Median :4.35   Median :1.300   virginica : 0  
 Mean   :5.936   Mean   :2.770   Mean   :4.26   Mean   :1.326                  
 3rd Qu.:6.300   3rd Qu.:3.000   3rd Qu.:4.60   3rd Qu.:1.500                  
 Max.   :7.000   Max.   :3.400   Max.   :5.10   Max.   :1.800                  
-------------------------------------------------------------- 
iris$Species: virginica
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.900   Min.   :2.200   Min.   :4.500   Min.   :1.400   setosa    : 0  
 1st Qu.:6.225   1st Qu.:2.800   1st Qu.:5.100   1st Qu.:1.800   versicolor: 0  
 Median :6.500   Median :3.000   Median :5.550   Median :2.000   virginica :50  
 Mean   :6.588   Mean   :2.974   Mean   :5.552   Mean   :2.026                  
 3rd Qu.:6.900   3rd Qu.:3.175   3rd Qu.:5.875   3rd Qu.:2.300                  
 Max.   :7.900   Max.   :3.800   Max.   :6.900   Max.   :2.500     

cela fonctionne en effet et le résultat est très surprenant. Il s'agit d'un objet de classe by que le long de Species (disons, pour chacun d'entre eux) calcule la summary de chaque variable.

Notez que si le premier argument est un data frame la fonction distribuée doit avoir une méthode pour cette classe d'objets. Par exemple, si nous utilisons ce code avec l'objet mean nous aurons ce code qui n'a aucun sens :

 by(iris, iris$Species, mean)
iris$Species: setosa
[1] NA
------------------------------------------- 
iris$Species: versicolor
[1] NA
------------------------------------------- 
iris$Species: virginica
[1] NA
Warning messages:
1: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
2: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA
3: In mean.default(data[x, , drop = FALSE], ...) :
  argument is not numeric or logical: returning NA

AGGREGAT

aggregate peut être considéré comme un autre mode d'utilisation différent. tapply si nous l'utilisons de cette manière.

at <- tapply(iris$Sepal.Length , iris$Species , mean)
ag <- aggregate(iris$Sepal.Length , list(iris$Species), mean)

 at
    setosa versicolor  virginica 
     5.006      5.936      6.588 
 ag
     Group.1     x
1     setosa 5.006
2 versicolor 5.936
3  virginica 6.588

Les deux différences immédiates sont que le deuxième argument de l'option aggregate doit être une liste tandis que tapply peut (non obligatoire) soit une liste et que la sortie de aggregate est un cadre de données tandis que celui de tapply est un array .

Le pouvoir de aggregate est qu'il peut traiter facilement des sous-ensembles de données avec subset et qu'il dispose de méthodes pour ts les objets et formula également.

Ces éléments font aggregate plus facile de travailler avec cela tapply dans certaines situations. Voici quelques exemples (disponibles dans la documentation) :

ag <- aggregate(len ~ ., data = ToothGrowth, mean)

 ag
  supp dose   len
1   OJ  0.5 13.23
2   VC  0.5  7.98
3   OJ  1.0 22.70
4   VC  1.0 16.77
5   OJ  2.0 26.06
6   VC  2.0 26.14

Nous pouvons obtenir la même chose avec tapply mais la syntaxe est légèrement plus difficile et la sortie (dans certaines circonstances) moins lisible :

att <- tapply(ToothGrowth$len, list(ToothGrowth$dose, ToothGrowth$supp), mean)

 att
       OJ    VC
0.5 13.23  7.98
1   22.70 16.77
2   26.06 26.14

Il y a d'autres moments où nous ne pouvons pas utiliser by o tapply et nous devons utiliser aggregate .

 ag1 <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)

 ag1
  Month    Ozone     Temp
1     5 23.61538 66.73077
2     6 29.44444 78.22222
3     7 59.11538 83.88462
4     8 59.96154 83.96154
5     9 31.44828 76.89655

Nous ne pouvons pas obtenir le résultat précédent avec tapply en un seul appel mais nous devons calculer la moyenne le long de Month pour chaque élément, puis les combiner (notez également que nous devons appeler la fonction na.rm = TRUE parce que le formula méthodes de l aggregate a par défaut la fonction na.action = na.omit ) :

ta1 <- tapply(airquality$Ozone, airquality$Month, mean, na.rm = TRUE)
ta2 <- tapply(airquality$Temp, airquality$Month, mean, na.rm = TRUE)

 cbind(ta1, ta2)
       ta1      ta2
5 23.61538 65.54839
6 29.44444 79.10000
7 59.11538 83.90323
8 59.96154 83.96774
9 31.44828 76.90000

tandis qu'avec by nous n'arrivons pas à réaliser qu'en fait l'appel de fonction suivant renvoie une erreur (mais il est fort probable qu'elle soit liée à la fonction fournie, mean ) :

by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)

D'autres fois, les résultats sont les mêmes et les différences se situent uniquement au niveau de l'objet de la classe (et ensuite de la manière dont il est montré/imprimé et pas seulement -- exemple, comment le sous-ensembler) :

byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)

Le code précédent permet d'atteindre le même objectif et les mêmes résultats, à certains moments, le choix de l'outil à utiliser n'est qu'une question de goûts et de besoins personnels ; les deux objets précédents ont des besoins très différents en termes de sous-ensembles.

0 votes

Comme je l'ai dit, le pouvoir de by se manifeste lorsque nous ne pouvons pas utiliser tapply ; le code suivant en est un exemple : CE SONT LES MOTS QUE VOUS AVEZ UTILISÉS CI-DESSUS. Et vous avez donné un exemple de calcul du résumé. Eh bien, disons que le résumé statistique peut être calculé, mais qu'il devra être nettoyé : ex. data.frame(tapply(unlist(iris[,-5]),list(rep(iris[,5],ncol(i‌​ris[-5])),col(iris[-‌​5])),summary)) c'est une utilisation de tapply . With the right splitting there is nothing you cant do with tapply . The only thing is it returns a matrix. Please be careful by saying we cant use tapply``

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X