2015-12-02 89 views
1

假设我在环境e中定义了两个类似的大对象x,y(datatable)。 我想用类似的方法改变x或y的很大一部分,而不用在f的执行环境中创建x或y的副本。例如:将值分配给R中另一个环境中的对象的一部分

e <- new.env() 
e$x <- c(1,2,3) # imagine this to be BIG (ie. dataframe with 200k vars each 500k rows) 
e$y <- c(4,5,6) # same here 
e$v <- 2  # minor variables 

f <- function(var_str, env, input){ 

    # do some computation on parts of var_str which is either "x" or "y" 
    # and store these right back into e$x or e$y, respectively. 
    # ie 

    str <- paste0(var_str,"[2:3] <- (",var_str,"[2:3])^2 + rep(v,2) + ", deparse(input1),"^3/c(100,101)") 
    eval(parse(text=str), envir= e) 

    # this does work but I can image there is an easier/more elegant way 
    # of doing this. 
} 

我想定义在全球环境的功能,该功能适用​​于E $ x和E $ y随输入不同的变量。 IE浏览器。执行

f("x", e, c(1,2)) 
f("y", e, c(3,4)) 

有没有人有一个优雅的解决方案。

+0

也许你可以得到你想要使用R6类:https://cran.r-project.org/web/packages/R6/vignettes/Introduction.html –

回答

0

出于好奇,我试着用the simple example in the R6 tutorial工作以及与此想出了(复制作为控制台成绩单)。我真的不知道它是否符合请求的非复制要求,但它似乎是在原地修改对象。

# Assumes one has created an R6 constructor named `RC` ... 
# slightly extended from the example in section 
RC <- setRefClass("RC", 
    fields = list(x = 'ANY'), 
    methods = list(
    getx = function() x, 
    setx = function(value) x <<- value, 
    setsub = function(i,j,val) x[i,j] <<- val 
) 
) 

#--- execution --- 
rc <- RC$new() 
rc$setx(matrix(1:20, 4,5)) 
rc 
# --- result ---  
Reference class object of class "RC" 

Field "x": 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 5 9 13 17 
[2,] 2 6 10 14 18 
[3,] 3 7 11 15 19 
[4,] 4 8 12 16 20 

测试类特定的setsub功能:

rc$setsub(4,5,0) #Test of setting a single element within an object to a new value 
rc 
#-------  
Reference class object of class "RC" 
Field "x": 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 5 9 13 17 
[2,] 2 6 10 14 18 
[3,] 3 7 11 15 19 
[4,] 4 8 12 16 0 

rc$setsub(1:4,1:4,0) #Test of setting a range of elements within an object to a new value 
rc 
# --------- 
Reference class object of class "RC" 
Field "x": 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 0 0 0 0 17 
[2,] 0 0 0 0 18 
[3,] 0 0 0 0 19 
[4,] 0 0 0 0 0 

所以通过setsub这个(看得很轻测试)实施[<- -function的确实成功。使用self参考一个单一的努力来扩展这个例子确实失败了。

+0

是的,我也尝试过“分配”,但是据我所知,该函数并不能让你在环境e中填充部分对象x和y。 – Robbin

+0

唯一可让您“就地”重新分配的函数集,即通过引用,即Rcpp或data.table包中的那些函数。 R是一种承诺(类似于按值)的语言。 –

+0

这看起来很有前途!我看看它。谢谢! – Robbin

0

eval(parse())是要避免的。您可以参考的环境是这样的:

e <- new.env() 
e$x <- c(1,2,3) # imagine this to be BIG (ie. dataframe with 200k vars each 500k rows) 
e$y <- c(4,5,6) # same here 
e$v <- 2  # minor variables 

f <- function(var_str, env, input){ 

    # do some computation on parts of var_str which is either "x" or "y" 
    # and store these right back into e$x or e$y, respectively. 
    # ie 
    env[[var_str]][2:3] <- (env[[var_str]][2:3])^2 + rep(env$v,2) + input^3/input 

} 


f("x", e, 1:2) 
e$x 
#[1] 1 7 15 
+0

啊这似乎是一个很好的解决方案,但没有这样做环境e中的var_str中的变量的副本? – Robbin

+0

Base R子分配当然是一个副本。但是,这是一个无关的问题,因为无论您分配的环境如何,副本都是必需的。如果这是问题,请使用实现按引用分配的类或函数。例如,存在package data.table(对于类似于数据框架的结构),或者可以编写一个通过引用分配的Rcpp函数。 – Roland

相关问题