studio - superponer graficas en r
¿Por qué usar la asignación es malo? (3)
Esta publicación ( Evaluación diferida en R - ¿se asigna afectado? ) Cubre algunos puntos en común, pero no estoy seguro si responde mi pregunta.
Dejé de usar assign
cuando descubrí la familia de apply
un tiempo, aunque solo por razones de elegancia en situaciones como esta:
names.foo <- letters
values.foo <- LETTERS
for (i in 1:length(names.foo))
assign(names.foo[i], paste("This is: ", values.foo[i]))
que puede ser reemplazado por:
foo <- lapply(X=values.foo, FUN=function (k) paste("This is :", k))
names(foo) <- names.foo
Esta es también la razón por la cual ( http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f ) R-faq dice que esto debe evitarse.
Ahora, sé que assign
generalmente está mal visto. ¿Pero hay otras razones que no sé? Sospecho que puede interferir con el alcance o la evaluación perezosa, pero no estoy seguro? El código de ejemplo que demuestra tales problemas será genial.
Como fuente de fortune(236)
, pensé que agregaría un par de ejemplos (véase también fortune(174)
).
Primero, un cuestionario. Considera el siguiente código:
x <- 1
y <- some.function.that.uses.assign(rnorm(100))
Después de ejecutar las 2 líneas de código anteriores, ¿cuál es el valor de x
?
La función assign
se utiliza para confirmar "Acción a distancia" (ver http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming) o google para ello). Esta es a menudo la fuente de errores difíciles de encontrar.
Creo que el mayor problema con la assign
es que tiende a llevar a las personas por caminos de pensamiento que los alejan de mejores opciones. Un ejemplo simple son los 2 juegos de código en la pregunta. La solución de aplicación es más elegante y debe promoverse, pero el mero hecho de que la gente aprenda acerca de la función de assign
lleva a las personas a la opción de bucle. Luego deciden que necesitan hacer la misma operación en cada objeto creado en el bucle (que sería simplemente otro simple lapply
o sapply
si se sapply
la solución elegante) y recurrir a un bucle aún más complicado que involucra tanto get
como apply
junto con feos llamados a paste
. Entonces aquellos enamorados de assign
intentan hacer algo como:
curname <- paste(''myvector['', i, '']'')
assign(curname, i)
Y eso no hace exactamente lo que esperaban, lo que lleva a quejarse de R (que es tan justo como quejarse de que la casa de mi vecino está demasiado lejos porque decidí caminar por el camino de la manzana) o incluso peor, profundizar en el uso de eval
y parse
para obtener su cadena construida para "trabajar" (que luego conduce a la fortune(106)
y la fortune(181)
).
En realidad esas dos operaciones son bastante diferentes. El primero te da 26 objetos diferentes, mientras que el segundo te da solo uno. El segundo objeto será mucho más fácil de usar en los análisis. Así que supongo que diría que ya has demostrado la desventaja principal de la assign
, es decir, la necesidad de utilizar siempre get
para acorralar o reunir todos los objetos individuales con nombres similares que ahora están "sueltos" en el entorno global. Intenta imaginar cómo harías en serie algo con esos 26 objetos separados. Una simple lapply(foo, func)
será suficiente para la segunda estrategia.
Esa cita de las Preguntas frecuentes realmente solo dice que usar asignación y luego asignar nombres es más fácil, pero no implica que sea "mala". Resulta que lo leí como "menos funcional", ya que en realidad no está devolviendo un valor asignado. El efecto parece ser un efecto secundario (y en este caso la estrategia de assign
da como resultado 26 efectos secundarios diferentes). El uso de la assign
parece ser adoptado por personas que provienen de lenguajes que tienen variables globales como una forma de evitar tomar la "Vía True R", es decir, la programación funcional con objetos de datos. Realmente deberían aprender a usar listas en lugar de ensuciar su espacio de trabajo con elementos con nombres individuales.
Hay otro paradigma de asignación que se puede usar:
foo <- setNames( paste0(letters,1:26), LETTERS)
Eso crea un vector atómico con nombre en lugar de una lista con nombre, pero el acceso a los valores en el vector todavía se hace con los nombres dados a [
.
Me gustaría señalar que la assign
se debe usar con el environment
s.
Desde ese punto de vista, lo "malo" en el ejemplo anterior es utilizar una estructura de datos no del todo apropiada (el entorno base en lugar de una list
o data.frame
, vector
, ...).
Nota al margen: también para el environment
s, los operadores $
y $<-
funcionan, por lo que en muchos casos la assign
y get
explícita no es necesaria allí, tampoco.