tutorial - tags$div shiny
AsignaciĆ³n por referencia en conjuntos de datos de paquetes cargados (2)
Esto no tiene nada que ver con los conjuntos de datos o el bloqueo, puede reproducirlo simplemente usando
DT<-unserialize(serialize(data.table(b = 1:5),NULL))
foo(DT)
DT
Sospecho que tiene que ver con el hecho de que data.table
tiene que volver a crear el extptr dentro del objeto en el primer acceso en DT
, pero lo está haciendo en una copia, por lo que no hay forma de que pueda compartir la modificación con el original. en el entorno global.
[De Mateo] Exactamente.
DT<-unserialize(serialize(data.table(b = 1:3),NULL))
DT
b
1: 1
2: 2
3: 3
DT[,newcol:=42]
DT # Ok. DT rebound to new shallow copy (when direct)
b newcol
1: 1 42
2: 2 42
3: 3 42
DT<-unserialize(serialize(data.table(b = 1:3),NULL))
foo(DT)
b a
1: 1 1
2: 2 1
3: 3 1
DT # but not ok when via function foo()
b
1: 1
2: 2
3: 3
DT<-unserialize(serialize(data.table(b = 1:3),NULL))
alloc.col(DT) # alloc.col needed first
b
1: 1
2: 2
3: 3
foo(DT)
b a
1: 1 1
2: 2 1
3: 3 1
DT # now it''s ok
b a
1: 1 1
2: 2 1
3: 3 1
O, no pase DT
a la función, solo refiérase a ella directamente. Use data.table
como una base de datos: algunas tablas de nombres fijos en .GlobalEnv
.
DT <- unserialize(serialize(data.table(b = 1:5),NULL))
foo <- function() {
DT[, newcol := 7]
}
foo()
b newcol
1: 1 7
2: 2 7
3: 3 7
4: 4 7
5: 5 7
DT # Unserialized data.table now over-allocated and updated ok.
b newcol
1: 1 7
2: 2 7
3: 3 7
4: 4 7
5: 5 7
Estoy en el proceso de crear un paquete que utiliza una data.table
datos como un conjunto de datos y tiene un par de funciones que se asignan por referencia usando :=
.
He construido un paquete simple para demostrar mi problem
library(devtools)
install_github(''foo'',''mnel'')
Contiene dos funciones
foo <- function(x){
x[, a := 1]
}
fooCall <- function(x){
eval(substitute(x[, a :=1]),parent.frame(1))
}
y un conjunto de datos (no cargado perezoso) DT
, creado usando
DT <- data.table(b = 1:5)
save(DT, file = ''data/DT.rda'')
Cuando instalo este paquete, entiendo que foo(DT)
debe asignar por referencia dentro de DT
.
library(foo)
data(DT)
foo(DT)
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
# However this has not assigned by reference within `DT`
DT
b
1: 1
2: 2
3: 3
4: 4
5: 5
Si uso lo mas correct
tracmem(DT)
DT <- foo(DT)
# This works without copying
DT
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
untracemem(DT)
Si utilizo eval
y substitute
dentro de la función.
fooCall(DT)
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
# it does assign by reference
DT
b a
1: 1 1
2: 2 1
3: 3 1
4: 4 1
5: 5 1
Debería seguir con
-
DT <- foo(DT)
o la rutaeval
/substitute
, o - ¿Hay algo que no entiendo sobre cómo los
data
cargan los conjuntos de datos, incluso cuando no son perezosos?
Otra solución es usar inst/extdata
para guardar el archivo rda
(que contendría cualquier número de objetos data.table) y tener un archivo DT.r
dentro del subdirectorio de data
# get the environment from the call to `data()`
env <- get(''envir'', parent.frame(1))
# load the data
load(system.file(''extdata'',''DT.rda'', package= ''foo''), envir = env)
# overallocate (evaluating in correct environment)
if(require(data.table)){
# the contents of `DT.rda` are known, so write out in full
evalq(alloc.col(DT), envir = env)
}
# clean up so `env` object not present in env environment after calling `data(DT)`
rm(list = c(''env''), envir = env)
}