• analyse-de-donnes-cestad
  • analytics_tools_original
  • data-minig1
  • data-minig2
  • Data-Mining-1030
  • Big-data-azzurro
  • marketing-statistics
Enquêtes
Collete des données
Traitement des données
Analyse des données
 
Programmation
Programmation statistique
Developpement des macros
Modélisation et plus encore
 
Data Mining
Exploration des données
Modélisation prédictive
Big Data
 
Formations certifiantes
Formations à la carte
Semilaires et conférences

 

 

 

Une fonction - formellement appelée fermeture dans la documentation R - comprend non seulement ses arguments et son corps, mais aussi son environnement. Ce dernier est constitué de la collection d'objets présents au moment de la création de la fonction. Une compréhension de la façon dont les environnements fonctionnent dans R est essentielle pour écrire des fonctions R efficaces.


1 L'environnement de premier niveau
Considérez cet exemple:

  1. >w<-12
  2. > f <- function(y) {
  3. + d <- 8
  4. + h <- function() {
  5. + return(d
  6. *
  7. (w+y))
  8. +}
  9. + return(h())
  10. +}
  11. <environment: R_GlobalEnv>
Source code
Ici, la fonction f () est créée au niveau supérieur, c'est-à-dire à l'invite de commande inter¬prètre, et a donc l'environnement de niveau supérieur, qui dans la sortie R est appelé R_GlobalEnv mais que vous référez de manière confuse Code R comme .GlobalEnv. Si vous exécutez un programme R en tant que fichier de commandes, cela est également considéré comme le niveau supérieur.
La fonction ls () répertorie les objets d'un environnement. Si vous l'appelez au niveau supérieur, vous obtenez l'environnement de niveau supérieur. Essayons avec notre code d'exemple:

  1. mo
  2. [1] "f" "w"
Source code
  1. mo
  2. [1] "f" "w"
Source code
Comme vous pouvez le voir, l'environnement de niveau supérieur inclut ici la variable w, qui est effectivement utilisée dans f (). Notez que f () est ici aussi, car les fonctions sont en effet des objets et nous l'avons créé au niveau supérieur. Aux niveaux autres que le sommet, ls () fonctionne un peu différemment, comme vous le verrez dans la section 7.6.3.
Vous obtenez un peu plus d'informations de ls.str ():

  1. > ls.str()
  2. f : function (y)
  3. w : num 12
Source code
Ensuite, nous verrons comment w et d'autres variables entrent en jeu dans f ().


2 La hiérarchie de portée
Nous allons d'abord obtenir une vue d'ensemble intuitive de la façon dont fonctionne la portée dans R, puis la relier aux environnements.
Si nous travaillons avec le langage C, nous dirons que la variable w dans la section précédente est globale à f (), tandis que d est local à f (). Les choses sont similaires dans R, mais R est plus hiérarchique. En C, nous n'aurions pas de fonctions définies dans les fonctions, comme nous avons avec h () à l'intérieur de f () dans notre exemple. Cependant, puisque les fonctions sont des objets, il est possible - et parfois souhaitable du point de vue de l'objectif d'encapsulation de la programmation orientée objet - de définir une fonction dans une fonction; nous créons simplement un objet, que nous pouvons faire n'importe où.
Ici, nous avons h () étant local à f (), tout comme d. Dans une telle situation, il est logique que la portée soit hiérarchique. Ainsi, R est établi de sorte que d, qui est local à f (), est à son tour global à h (). Il en est de même pour y, car les arguments sont considérés comme des sections locales dans R.
De même, la nature hiérarchique de la portée implique que puisque w est global à f (), elle est aussi globale à h (). En effet, nous utilisons w dans h ().
En termes d'environnements, alors, l'environnement de h () consiste en ce que les objets sont définis à l'instant h () existe; c'est-à-dire au moment où cette affectation est exécutée:

  1. h <- function() {
  2. }
  3. *
  4. (w+y))
Source code
(Si f () est appelé plusieurs fois, h () apparaît plusieurs fois, sortant de son existence chaque fois que f () retourne.)
Quel sera donc l'environnement de h ()? Eh bien, au moment de la création de h (), les objets d et y sont créés dans f (), plus l'environnement (w) de f ().
En d'autres termes, si une fonction est définie dans un autre, alors l'environnement de cette fonction interne est constitué de l'environnement de l'environnement externe, plus tout ce que les locaux ont été créés jusqu'à présent dans l'environnement externe. Avec une imbrication multiple des fonctions, vous avez une séquence imbriquée d'environnements de plus en plus grands, la racine étant constituée des objets de niveau supérieur.
Essayons le code:

  1. > f(2)
  2. [1] 112
Source code
  1. > f(2)
  2. [1] 112
Source code
Qu'est-il arrivé? L'appel f (2) a abouti à la définition de la variable locale d à 8, suivie de l'appel h (). Ce dernier a évalué d * (w + y) - c'est-à-dire 8 * (i2 + 2) - nous donnant 112.
Notez attentivement le rôle de w. L'interprète R a trouvé qu'il n'y avait pas de variable locale de ce nom, donc il est passé au niveau supérieur suivant - dans ce cas, le niveau supérieur - où il a trouvé une variable w avec la valeur 12.
Gardez à l'esprit que h () est local à f () et invisible au niveau supérieur.

  1. >h
  2. Error: object 'h' not found
Source code
Il est possible (mais pas souhaitable) d'autoriser délibérément les conflits de noms dans cette hiérarchie. Dans notre exemple, par exemple, nous pourrions avoir une variable locale d dans h (), en conflit avec celle de f (). Dans une telle situation, l'environnement le plus interne est utilisé en premier. Dans ce cas, une référence à d dans h () ferait référence aux d, et non à f () de h ().
Les environnements créés par héritage de cette manière sont généralement désignés par leurs emplacements de mémoire. Voici ce qui s'est passé après avoir ajouté une instruction print à f () (en utilisant edit (), non montré ici) et en exécutant le code:

  1. >f
  2. }
  3. d<-8
  4. h <- function() {
  5. *
  6. (w+y))
  7. }
  8. return(h())
  9. > f(2)
  10. <environment: 0x875753c>
  11. [1] 112
Source code

Comparez tout cela à la situation dans laquelle les fonctions ne sont pas imbriquées:
  1. >f
  2. }
  3. d<-8
  4. return(h())
  5. >h
  6. }
  7. *
  8. (w+y))
Source code
Le résultat est le suivant:
  1. > f(5)
  2. Error in h() : object 'd' not found
Source code
Cela ne fonctionne pas car d n'est plus dans l'environnement de h (), car h () est défini au niveau supérieur. Ainsi, une erreur est générée.
Pire, si, par hasard, il y avait eu une variable indépendante d dans l'environnement de niveau supérieur, nous n'obtenions pas de message d'erreur mais obtenions des résultats incorrects.
Vous pourriez vous demander pourquoi R ne s'est pas plaint de l'absence de y dans la définition alternative de h () dans l'exemple précédent. Comme mentionné précédemment,
R n'évalue pas une variable jusqu'à ce qu'elle en ait besoin dans le cadre d'une politique appelée évaluation paresseuse. Dans ce cas, R avait déjà rencontré une erreur avec d et n'a donc jamais atteint le point où il essaierait d'évaluer y.
Le correctif est de passer d et y comme arguments:
  1. >f
  2. d<-8
  3. return(h(d,y))
  4. }
  5. >h
  6. function(dee,yyy) {
  7. return(dee
  8. *
  9. (w+yyy))
  10. }
  11. > f(2)
  12. [1] 88
Source code
D'accord, regardons une dernière variation:
  1. >f
  2. function(y,ftn) {
  3. d<-8
  4. return(ftn(d,y))
  5. }
  6. >h
  7. function(dee,yyy) {
  8. }
  9. return(dee
  10. *
  11. (w+yyy))
  12. >w<-12
  13. > f(3,h)
  14. <environment: R_GlobalEnv>
  15. [1] 120
Source code
Lorsque f () est exécuté, l'argument formel ftn est apparié par l'argument réel h. Étant donné que les arguments sont traités comme des sections locales, vous pouvez supposer que ftn pourrait avoir un environnement différent du niveau supérieur. Mais comme discuté, un cloître inclut l'environnement, et ainsi ftn a l'environnement de h.
Notez bien que tous les exemples concernant les variables nonlocales concernent les lectures, pas les écritures. Le cas des écritures est crucial et sera traité dans la section 7.8.1.

3 Plus d'informations sur ls ()
Sans arguments, un appel à ls () à partir d'une fonction renvoie les noms des variables locales en cours (y compris les arguments). Avec l'argumentation de l'environnement, il imprimera les noms des locaux de n'importe quelle trame de la chaîne d'appel.
  1. >f
  2. d<-8
  3. return(h(d,y))
  4. }
  5. >h
  6. function(dee,yyy) {
  7. }
  8. print(ls(envir=parent.frame(n=1)))
  9. return(dee
  10. > f(2)
  11. [1] "dee" "yyy"
  12. [1] "d" "y"
  13. [1] 112
  14. *
  15. (w+yyy))
Source code
Avec parent.frame (), l'argument n spécifie le nombre d'images à monter dans la chaîne d'appel. Ici, nous étions en train d'exécuter h (), qui avait été appelé à partir de f (), donc spécifier n = 1 nous donne le cadre de f (), et ainsi nous obtenons ses locaux.
 
4 Les fonctions n'ont (presque) aucun effet secondaire
Une autre influence de la philosophie de la programmation fonctionnelle est que les fonctions ne changent pas les variables non locales; c'est-à-dire, généralement, il n'y a pas d'effets secondaires. Grosso modo,
le code dans une fonction a un accès en lecture à ses variables nonlocales, mais il n'a pas accès en écriture à celles-ci. Notre code peut sembler réassigner ces variables, mais l'action n'affectera que les copies, pas les variables elles-mêmes. Démontrons cela en ajoutant un peu plus de code à notre exemple précédent.
  1. >w<-12
  2. >f
  3. }
  4. d<-8
  5. w<-w+1
  6. y<-y-2
  7. h <- function() {
  8. *
  9. (w+y))
  10. }
  11. return(h())
  12. >t<-4
  13. > f(t)
  14. [1] 13
  15. [1] 120
  16. >w
  17. [1] 12
  18. >t
  19. [1] 4
Source code
Donc, w au niveau supérieur n'a pas changé, même s'il semble changer dans f (). Seule une copie locale de w, dans f (), a changé. De même, la variable de niveau supérieur t n'a pas changé, même si son argument formel associé y a changé.
NOTE Plus précisément, les références au local w vont en fait au même emplacement mémoire que le local, jusqu'à ce que la valeur du local change. Dans ce cas, un nouvel emplacement de mémoire est utilisé.
Une exception importante à cette nature en lecture seule des globaux se pose avec l'opérateur de super-assignement, dont nous parlerons plus loin dans la section 7.8.1.