studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones r function dataframe

reales - libro de android studio en español pdf



Actualizar el marco de datos a través de la función no funciona (5)

Cambiando <- to << - en tu función, también funciona el truco, mira el R-manual . Cita de esa página:

Los operadores << - y - >> normalmente solo se utilizan en funciones y hacen que se realice una búsqueda a través de los entornos principales para una definición existente de la variable que se está asignando. Si se encuentra dicha variable (y su enlace no está bloqueado), entonces su valor se redefine, de lo contrario la asignación tiene lugar en el entorno global.

Su código debería ser:

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) test.fun <- function (x) { test[test$v1==x,"v2"] <<- 10 print(test) } test.fun(1)

Me encontré con un pequeño problema usando R ...

En el siguiente marco de datos

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0)

Quiero cambiar los valores de v2 en las filas donde v1 es 1.

test[test$v1==1,"v2"] <- 10

funciona bien

test v1 v2 1 1 10 2 1 10 3 1 10 4 2 0 5 2 0 6 2 0

Sin embargo, necesito hacer eso en una función.

test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) test.fun <- function (x) { test[test$v1==x,"v2"] <- 10 print(test) }

Llamar a la función parece funcionar.

test.fun(1) v1 v2 1 1 10 2 1 10 3 1 10 4 2 0 5 2 0 6 2 0

Sin embargo, cuando ahora miro la prueba:

test v1 v2 1 1 0 2 1 0 3 1 0 4 2 0 5 2 0 6 2 0

no funcionó ¿Hay algún comando que le indique a R que realmente actualice el marco de datos en la función? ¡Muchas gracias por cualquier ayuda!


Creo que esto sucede debido a los diferentes environments que se evalúan. Su función copia la test del entorno global a un entorno local temporal (que se crea en la llamada de función) y luego la test solo se evalúa (es decir, se modifica) en este entorno local.

Podrías superar este problema usando la súper-asignación <<- , pero esto NO es recomendable y te llevará a problemas horribles e imprevistos (tu computadora detecta un virus, tu novia comienza a engañarte, ...).

En general, la solución dada por Joshua Ulrich es la forma de abordar este tipo de problemas. Pasa el objeto original y lo devuelve. En la llamada de función asigna el resultado a su objeto original.


Es una buena práctica no cambiar variables globales en funciones, ya que esto puede tener efectos secundarios indeseables. Para evitar esto en R, cualquier cambio en los objetos dentro de una función solo cambia las copias que son locales al environment esa función.

Si realmente desea cambiar la prueba, debe asignar el valor de retorno de la función a la prueba (sería mejor escribir la función con un valor de retorno más explícito,

test <- test.fun(1)

O elija el entorno global para asignarlo a test.fun ,

test.fun <- function (x) { test[test$v1==x,"v2"] <- 10 print(test) assign("test",test,.GlobalEnv) }


Podrías escribir una función de reemplazo. Esta es una función con un nombre que termina en ''<-'' y esencialmente lo envuelve en un:

foo = bar (foo)

envoltura. Entonces en tu caso:

> "setV2<-" = function (x,value,m){x[x$v1==m,"v2"]=value;return(x)} > test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) > setV2(test,1)=10 > test v1 v2 1 1 10 2 1 10 3 1 10 4 2 0 5 2 0 6 2 0 > setV2(test,2)=99 > test v1 v2 1 1 10 2 1 10 3 1 10 4 2 99 5 2 99 6 2 99

Tenga en cuenta que debe citar el nombre de la función en la creación o R se confunde.


test en su función es una copia del objeto de su entorno global (supongo que es allí donde está definido). La asignación ocurre en el entorno actual a menos que se especifique lo contrario, por lo que debe decirle a R que desea asignar la copia local de la test a la test en .GlobalEnv .

Y es una buena forma pasar todos los objetos necesarios como argumentos a la función.

test.fun <- function (x, test) { test[test$v1==x,"v2"] <- 10 assign(''test'',test,envir=.GlobalEnv) #test <<- test # This also works, but the above is more explicit. } (test.fun(1, test)) # v1 v2 #1 1 10 #2 1 10 #3 1 10 #4 2 0 #5 2 0 #6 2 0

Personalmente, return(test) y haría la tarea fuera de la función, pero no estoy seguro si puede hacer esto en su situación real.

test.fun <- function (x, test) { test[test$v1==x,"v2"] <- 10 return(test) } test <- data.frame(v1=c(rep(1,3),rep(2,3)),v2=0) (test <- test.fun(1, test)) # v1 v2 #1 1 10 #2 1 10 #3 1 10 #4 2 0 #5 2 0 #6 2 0