46 votes

Dans R, quel est exactement le problème avec le fait d'avoir des variables avec le même nom que la base de fonctions R?

Il semble être généralement considérée comme mauvaise programmation s'exercer à utiliser des noms de variables qui ont des fonctions de base de R avec le même nom.

Par exemple, il est tentant d'écrire:

data <- data.frame(...)
df   <- data.frame(...)

Maintenant, la fonction data charges ensembles de données alors que la fonction df calcule la f d'une fonction de densité.

De même, il est tentant d'écrire:

a <- 1
b <- 2
c <- 3

Ceci est considéré comme une mauvaise forme, car la fonction c combinera ses arguments.

Mais: Dans que la bête de somme de fonctions R, lm, pour calculer des modèles linéaires, data est utilisé comme un argument. En d'autres termes, data devient explicite d'une variable à l'intérieur de l' lm fonction.

Donc: Si la R du noyau de l'équipe peuvent utiliser les mêmes noms de variables et de fonctions, ce qui nous empêche de simples mortels?

La réponse n'est pas que la R vont se confondre. Essayez l'exemple suivant, où j'ai affecter explicitement une variable avec le nom c. R ne pas se confondre avec la différence entre la variable et la fonction:

c("A", "B")
[1] "A" "B"

c <- c("Some text", "Second", "Third")
c(1, 3, 5)
[1] 1 3 5

c[3]
[1] "Third"

La question: Quel est exactement le problème avec les variables avec le même nom que la base de la fonction R?

23voto

Gavin Simpson Points 72349

Il n'y a pas vraiment un. R ne seront pas normalement à la recherche d'objets (objets de fonction) lors de la recherche d'une fonction:

> mean(1:10)
[1] 5.5
> mean <- 1
> mean(1:10)
[1] 5.5
> rm(mean)
> mean(1:10)
[1] 5.5

Les exemples présentés par @Joris et @Sacha sont où les pauvres de codage vous attrape. Une meilleur façon d'écrire foo est:

foo <- function(x, fun) {
    fun <- match.fun(fun)
    fun(x)
}

Qui, lorsqu'il donne:

> foo(1:10, mean)
[1] 5.5
> mean <- 1
> foo(1:10, mean)
[1] 5.5

Il y a des situations où cela va vous attraper, et @Joris exemple avec na.omit est une, IIRC, est produit en raison de la non-standard d'évaluation utilisés dans lm().

Plusieurs Réponses ont également englobé l' T vs TRUE problème avec le masquage des fonctions de problème. En tant que T et TRUE ne sont pas des fonctions qui est un peu en dehors de la portée de @Andrie de la Question.

18voto

Joris Meys Points 38980

Le problème n'est pas tant l'ordinateur, mais l'utilisateur. En général, le code peut devenir beaucoup plus difficile à déboguer. Les fautes de frappe sont fait très facilement, donc si vous ne :

c <- c("Some text", "Second", "Third")
c[3]
c(3)

Vous obtenir des résultats corrects. Mais si vous manquez quelque part dans un code et tapez c(3) au lieu de c[3], trouver l'erreur ne sera pas facile.

La portée peut aussi conduire à beaucoup de confusion des rapports d'erreur. Suite à erronée de la fonction :

my.foo <- function(x){
    if(x) c <- 1
    c + 1
}

> my.foo(TRUE)
[1] 2
> my.foo(FALSE)
Error in c + 1 : non-numeric argument to binary operator

Avec des fonctions plus complexes, cela peut vous conduire sur une débogage sentier menant nulle part. Si vous remplacez c avec x dans la fonction ci-dessus, l'erreur de lecture "object 'x' not found". Qui va conduire beaucoup plus rapide de votre erreur de codage.

À côté de cela, il peut conduire à la plutôt du code source de confusion. Code comme celui - c(c+c(a,b,c)) intéresse de plus en plus dans le cerveau que c(d+c(a,b,d)). Encore une fois, c'est un exemple trivial, mais il peut faire une différence.

Et évidemment, vous pouvez obtenir trop d'erreurs. Lorsque vous vous attendez à une fonction, vous ne l'obtenez pas, ce qui peut donner lieu à une autre série de bugs gênants :

my.foo <- function(x,fun) fun(x)
my.foo(1,sum)
[1] 1
my.foo(1,c)
Error in my.foo(1, c) : could not find function "fun"

De façon plus réaliste (et de la vie réelle) exemple de comment cela peut causer des problèmes :

x <- c(1:10,NA)
y <- c(NA,1:10)
lm(x~y,na.action=na.omit)
# ... correct output ...
na.omit <- TRUE
lm(x~y,na.action=na.omit)
Error in model.frame.default(formula = x ~ y, na.action = na.omit, 
drop.unused.levels = TRUE) : attempt to apply non-function

Essayer de trouver quel est le problème ici, si l' na.omit <- TRUE se produit 50 lignes dans votre code...

Réponse édité après le commentaire de @Andrie pour inclure l'exemple de confusion des rapports d'erreur

11voto

Sacha Epskamp Points 14956

R est très robuste, mais ce à quoi vous pouvez penser à des façons de le casser. Prenons l'exemple de cette fonction:

foo <- function(x,fun) fun(x)

Qui simplement s'applique fun de x. Pas la plus belle façon de le faire, mais vous risquez de rencontrer ce de quelqu'un script ou donc. Cela fonctionne pour mean():

> foo(1:10,mean)
[1] 5.5

Mais si je assigner une nouvelle valeur à dire que c'pauses:

mean <- 1
foo(1:10,mean)

Error in foo(1:10, mean) : could not find function "fun"

Cela arrive très rarement, mais ça peut arriver. Il est également très déroutant pour les personnes si la même chose signifie deux choses:

mean(mean)

Car il est trivial d'utiliser tout autre nom que vous voulez, pourquoi ne pas utiliser un nom différent, puis de la base de fonctions R? Aussi, pour certains R de variables, cela devient encore plus important. Pensez à réaffecter le '+' fonction! Un autre bon exemple est la réaffectation de l' T et F , qui peut se casser autant de scripts.

3voto

Roman Luštrik Points 19295

Je pense que le problème est lorsque les gens utilisent ces fonctions dans l'environnement mondial et peut causer de la frustration en raison de certaines erreur inattendue vous ne devrait pas être. Imaginez-vous juste couru un exemple reproductible (peut-être assez longue) qui a remplacé celui de la fonction que vous utilisez dans votre simulation qui prend une éternité à arriver là où vous voulez et puis, soudain, il se décompose avec une drôle d'erreur. L'aide déjà existants en fonction des noms de variables dans un environnement fermé (comme une fonction) sont supprimés une fois la fonction ferme et ne devrait pas causer de dommage. En supposant que le programmeur est conscient de toutes les conséquences d'un tel comportement.

3voto

Nick Sabbe Points 6741

La réponse est simple. Bien, genre de.

La ligne de fond est que vous devriez éviter la confusion. Techniquement il n'y a pas de raison de donner à vos variables des noms propres, mais cela rend votre code plus facile à lire.

Imaginez avoir une ligne de code contenant quelque chose comme data()[1] ou similaire (cette ligne n'a probablement pas de sens, mais c'est seulement un exemple): bien qu'il soit clair pour vous maintenant que vous êtes à l'aide de données de la fonction ici, un lecteur qui l'a remarqué il y a un données.trame de données nommée il y, peuvent être confondues.

Et si vous n'êtes pas altruisticly incliné, rappelez-vous que le lecteur pourrait être vous dans une demi-année, en essayant de comprendre ce que l'on fait avec "ce vieux code".

Prendre d'un homme qui a appris à utiliser de longs noms de variables et des conventions de nommage: ça rapporte!

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