L'une des caractéristiques les plus connues et les plus utilisées de R est la famille de fonctions  apply (), telles que apply (), tapply () et lapply (). Ici, nous allons appliquer apply (), qui indique à R d'appeler une fonction spécifiée par l'utilisateur sur chacune des lignes ou chacune des colonnes d'une matrice.


1 Utilisation de la fonction apply ()
Voici la forme générale pour les matrices:

  1. apply(m,dimcode,f,fargs)
Source code
 où les arguments sont les suivants:
• m est la matrice.
• dimcode est la dimension, égale à 1 si la fonction s'applique aux lignes ou 2 pour les colonnes.
• f est la fonction à appliquer.
• fargs est un ensemble facultatif d'arguments à fournir à f.
Par exemple, nous appliquons ici la fonction mean () à chaque colonne d'une matrice z:
  1. > z
  2. [,1] [,2]
  3. [1,] 1 4
  4. [2,] 2 5
  5. [3,] 3 6
  6. > apply(z,2,mean)
  7. [1] 2 5
Source code

Dans ce cas, nous aurions pu utiliser la fonction colMeans (), mais cela représente un exemple simple d'application apply ().
Une fonction que vous écrivez vous est juste comme légitime à utiliser dans apply () comme n'importe quelle fonction intégrée R comme mean (). Voici un exemple en utilisant notre propre fonction f:
  1. > z
  2. [,1] [,2]
  3. [1,] 1 4
  4. [2,] 2 5
  5. [3,] 3 6
  6. > f <- function(x) x/c(2,8)
  7. > y <- apply(z,1,f)
  8. > y
  9. [,1] [,2] [,3]
  10. [1,] 0.5 1.000 1.50
  11. [2,] 0.5 0.625 0.75
Source code
Notre fonction f () divise un vecteur à deux éléments par le vecteur (2,8). (Le recopier serait utilisé si x avait une longueur supérieure à 2.) L'appel de la fonction apply () demande à R d'appeler f () sur chacune des rangées de z. La première ligne de ce genre est (1,4), donc dans l'appel à f (), l'argument réel correspondant à l'argument formel x est
(1,4). Ainsi, R calcule la valeur de (1,4) / (2,8), qui dans l'arithmétique vectorielle des éléments R est (0,5,0,5). Les calculs pour les deux autres lignes sont similaires.
Vous avez peut-être été surpris que la taille du résultat ici soit 2 par 3 plutôt que 3 par 2. Ce premier calcul, (0,5,0,5), se termine à la première colonne dans la sortie de apply (), pas le première rangée. Mais c'est le comportement de apply (). Si la fonction à appliquer renvoie un vecteur de k composants, alors le résultat de apply () aura k lignes. Vous pouvez utiliser la fonction de transposition matricielle t () pour la modifier si nécessaire, comme suit:
  1. > t(apply(z,1,f))
  2. [,1] [,2]
  3. [1,] 0.5 0.500
  4. [2,] 1.0 0.625
  5. [3,] 1.5 0.750
Source code
Si la fonction renvoie un scalaire (ce que nous savons n'est qu'un vecteur à un élément), le résultat final sera un vecteur, pas une matrice.
Comme vous pouvez le voir, la fonction à appliquer doit prendre au moins un argument. L'argument formel ici correspondra à un argument réel d'une ligne ou d'une colonne dans la matrice, comme décrit précédemment. Dans certains cas, vous aurez besoin d'arguments supplémentaires pour cette fonction, que vous pouvez placer en suivant le nom de la fonction dans votre appel de la fonction apply().
Par exemple, supposons que nous avons une matrice de 1s et 0s et que nous voulons créer un vecteur comme suit: Pour chaque ligne de la matrice, l'élément correspondant du vecteur sera soit 1 ou 0, selon que la majorité du premier d les éléments dans cette rangée sont 1 ou 0. Ici, d sera un paramètre que nous souhaitons peut-être varier. Nous pourrions faire ceci:
  1. > copymaj
  2. function(rw,d) {
  3. maj <- sum(rw[1:d]) / d
  4. return(if(maj > 0.5) 1 else 0)
  5. }
  6. > x
  7. [,1] [,2] [,3] [,4] [,5]
  8. [1,] 1 0 1 1 0
  9. [2,] 1 1 1 1 0
  10. [3,] 1 0 0 1 1
  11. [4,] 0 1 1 1 0
  12. > apply(x,1,copymaj,3)
  13. [1] 1 1 0 1
  14. > apply(x,1,copymaj,2)
  15. [1] 0 1 0 0
Source code

Ici, les valeurs 3 et 2 forment les arguments réels pour l'argument formel d dans copymaj (). Examinons ce qui s'est passé dans le cas de la rangée 1 de x. Cette rangée était constituée (1,0,1,1,0), dont les premiers éléments étaient (1,0,1). La majorité de ces trois éléments étaient 1s, donc copymaj () a renvoyé 1, et donc le premier élément de la sortie de apply () était un 1.
Contrairement à l'opinion commune, l'utilisation de apply () n'accélérera généralement pas votre code. Les avantages sont qu'il crée un code très compact, qui peut être plus facile à lire et à modifier, et vous évitez d'éventuels bogues dans le code d'écriture pour la mise en boucle. En outre, au fur et à mesure que R se rapproche de plus en plus du traitement en parallèle, les fonctions comme apply () deviennent de plus en plus importantes. Par exemple, la fonction clusterApply () dans le paquet de neige offre une certaine capacité de traitement parallèle en distribuant les données de la sous-matrice aux différents noeuds du réseau, chaque noeud appliquant essentiellement la fonction donnée sur sa sous-matrice.


2 Exemple étendu: recherche de valeurs aberrantes
Dans les statistiques, les valeurs aberrantes sont des points de données qui diffèrent grandement de la plupart des autres observations. En tant que tels, ils sont traités soit comme suspects (ils pourraient être erronés) ou non représentatifs (comme le revenu de Bill Gates parmi les revenus des citoyens de l'État de Washington). De nombreuses méthodes ont été conçues pour identifier les valeurs aberrantes. Nous allons construire un très simple ici.
Disons que nous avons des données de vente au détail dans une matrice rs. Chaque rangée de données est pour un magasin différent, et les observations dans une rangée sont des chiffres de vente quotidiens. Comme une approche simple (sans doute trop simple), écrivons un code pour identifier le plus
observation déviante pour chaque magasin. Nous allons définir cela étant donné que l'observation se situait le plus loin de la valeur médiane de ce magasin. Voici le code:

  1. findols <- function(x) {
  2. findol <- function(xrow) {
  3. mdn <- median(xrow)
  4. devs <- abs(xrow-mdn)
  5. }
  6. return(apply(x,1,findol))
  7. }
Source code
Notre appel sera le suivant:
findols (rs)
Comment cela fonctionnera-t-il? Tout d'abord, nous avons besoin d'une fonction à spécifier dans notre appel apply ().
Étant donné que cette fonction sera appliquée à chaque rangée de notre matrice de vente, notre description implique qu'elle doit signaler l'indice de l'observation la plus déviante dans une rangée donnée. Notre fonction findol () fait cela, dans les lignes 4 et 5. (Notez que nous avons défini une fonction dans un autre ici, une pratique courante si la fonction interne est courte). Dans l'expression xrow-mdn, nous soustrayons un nombre c'est un vecteur à un élément d'un vecteur qui aura généralement une longueur supérieure à 1. Ainsi, le recyclage est utilisé pour étendre mdn pour se conformer au front avant la soustraction.
Ensuite, dans la ligne 5, nous utilisons la fonction R which.max (). Au lieu de trouver la valeur maximale dans un vecteur, que la fonction max () fait, which.max () nous indique où cette valeur maximale se produit, c'est-à-dire l'index où elle se produit. C'est exactement ce dont nous avons besoin.
Enfin, dans la ligne 7, nous demandons à R d'appliquer findol () à chaque rangée de x, ce qui produit les indices de l'observation la plus déviante dans chaque rangée.