En R, ¿cuál es exactamente el problema de tener variables con el mismo nombre que las funciones R base?

En general, se considera una práctica de progtwigción deficiente utilizar nombres de variables que tengan funciones en la base R con el mismo nombre.

Por ejemplo, es tentador escribir:

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

Ahora, los data la función cargan conjuntos de datos mientras la función df calcula la función de densidad f.

Del mismo modo, es tentador escribir:

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

Esto se considera una mala forma porque la función c combinará sus argumentos.

Pero: en ese caballo de batalla de las funciones R, lm , para calcular modelos lineales, los data se usan como argumento. En otras palabras, los data convierten en una variable explícita dentro de la función lm .

Entonces: si el equipo central R puede usar nombres idénticos para variables y funciones, ¿qué nos detiene a los simples mortales?

La respuesta no es que R se confundirá. Pruebe el siguiente ejemplo, donde explícitamente asigno una variable con el nombre c . R no se confunde en absoluto con la diferencia entre variable y función:

 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 pregunta: ¿Cuál es exactamente el problema de tener una variable con el mismo nombre que la función base R?

No hay realmente uno. R no buscará normalmente objetos (objetos que no sean funciones) cuando busque una función:

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

Los ejemplos mostrados por @Joris y @Sacha son donde la pobre encoding te atrapa. Una mejor forma de escribir foo es:

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

Que cuando se utiliza da:

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

Hay situaciones en que esto lo atrapará, y el ejemplo de @ Joris con na.omit es uno, que IIRC está sucediendo debido a la evaluación estándar no estándar utilizada en lm() .

Varias respuestas también han combinado el problema T vs TRUE con el problema de enmascaramiento de funciones. Como T y TRUE no son funciones que están un poco fuera del scope de @ Andrie's Question.

El problema no es tanto la computadora, sino el usuario. En general, el código puede ser mucho más difícil de depurar. Los errores tipográficos se hacen muy fácilmente, por lo que si lo hace:

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

Obtienes los resultados correctos. Pero si omite algún lugar en un código y escribe c(3) lugar de c[3] , encontrar el error no será tan fácil.

El scope también puede generar informes de error muy confusos. Tome la siguiente función defectuosa:

 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 

Con funciones más complejas, esto puede llevarte a un camino de depuración que no lleva a ninguna parte. Si reemplaza c con x en la función anterior, el error indicará " object 'x' not found ". Eso conducirá mucho más rápido a su error de encoding.

Además de eso, puede conducir a un código bastante confuso. El código como c(c+c(a,b,c)) pide más al cerebro que c(d+c(a,b,d)) . Nuevamente, este es un ejemplo trivial, pero puede hacer la diferencia.

Y obviamente, puedes obtener errores también. Cuando esperas una función, no la obtendrás, lo que puede dar lugar a otro conjunto de errores molestos:

 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" 

Un ejemplo más realista (y de la vida real) de cómo esto puede causar problemas:

 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 

Intenta averiguar qué está mal aquí si na.omit <- TRUE ocurre 50 líneas en tu código ...

Respuesta editada después del comentario de @Andrie para incluir el ejemplo de informes confusos de errores

R es muy sólido con esto, pero puedes pensar en formas de romperlo. Por ejemplo, considere esta función:

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

Lo cual simplemente aplica fun a x . No es la manera más bonita de hacer esto, pero es posible que te encuentres con este script de alguien más o menos. Esto funciona para mean() :

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

Pero si le asigno un nuevo valor significa que se rompe:

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

Esto sucederá muy raramente, pero podría suceder. También es muy confuso para las personas si lo mismo significa dos cosas:

 mean(mean) 

Dado que es trivial utilizar cualquier otro nombre que desee, ¿por qué no utilizar un nombre diferente y luego funciones base R? Además, para algunas variables R esto se vuelve aún más importante. ¡Piensa en reasignar la función '+' ! Otro buen ejemplo es la reasignación de T y F que puede romper tantos guiones.

Creo que el problema es cuando las personas usan estas funciones en el entorno global y pueden causar frustración debido a algún error inesperado que no debería obtener. Imagine que acaba de ejecutar un ejemplo reproducible (tal vez bastante largo) que sobreescribió una de las funciones que está utilizando en su simulación que tarda años en llegar a donde lo desea y de repente se descompone con un error gracioso. El uso de nombres de funciones ya existentes para variables en un entorno cerrado (como una función) se elimina después de que la función se cierra y no debe causar daño. Asumiendo que el progtwigdor es consciente de todas las consecuencias de tal comportamiento.

La respuesta es simple. Bueno, más o menos.

La conclusión es que debes evitar la confusión. Técnicamente, no hay ninguna razón para dar a sus variables los nombres propios, pero hace que su código sea más fácil de leer.

Imagine tener una línea de código que contenga algo como data()[1] o similar (esta línea probablemente no tenga sentido, pero solo es un ejemplo): aunque ahora está claro que está usando datos de funciones, un lector que notó que había una data.frame llamada data allí, puede confundirse.

Y si no tiene inclinaciones altruistas, recuerde que el lector podría ser usted en medio año, tratando de descubrir qué estaba haciendo con “ese viejo código”.

Tómalo de un hombre que ha aprendido a usar nombres largos de variables y convenciones de nombres: ¡paga!

Estoy de acuerdo con @Gavin Simpson y @Nick Sabbe en que no existe realmente un problema, pero que esto es más una cuestión de legibilidad del código. Por lo tanto, como muchas cosas en la vida, es una cuestión de convención y consenso.

Y creo que es una buena convención dar el consejo general: ¡No nombre sus variables como funciones base R!

Este consejo funciona como otros buenos consejos. Por ejemplo, todos sabemos que no debemos beber demasiado y no comer demasiada comida poco saludable, pero de vez en cuando no podemos seguir estos consejos y emborracharnos mientras comemos demasiada comida chatarra.

Lo mismo es cierto para este consejo. Obviamente tiene sentido nombrar los datos del argumento de data . Pero tiene mucho menos sentido nombrar un vector de datos. Aunque puede haber situaciones en las que incluso esto parece apropiado. Pero trata de evitar esas situaciones para mayor claridad.

Si bien algunos idiomas pueden permitirlo, IF IF THEN THEN ELSE ELSE . En general, se considera una práctica muy pobre. No es que no deseemos darte la oportunidad de mostrar tu conocimiento avanzado del idioma, es que algún día tendremos que lidiar con ese código y no somos más que mortales.

Así que guarde sus trucos de progtwigción de romper las comstackciones nocturnas y déle a sus variables nombres razonables, con una carcasa consistente si se siente demasiado cálido y confuso.