要求 r 函数在全局环境中使用对象而不是对象的副本
Posted
技术标签:
【中文标题】要求 r 函数在全局环境中使用对象而不是对象的副本【英文标题】:Require r function to use objects in global environment rather than copy of object 【发布时间】:2018-05-04 09:45:39 【问题描述】:我(也许是无知)对 R 的理解是函数会在内存中创建对象的临时副本。即使全局环境中的对象太大而无法复制,我如何仍然使用函数来简化代码?还是建议只对大对象的必要部分进行子集化以供函数操作?
例子
# load two objects with 10 million rows and 500 columns
big.object.1 <- readRDS(file = "previously.created.dataframe.1")
big.object.2 <- readRDS(file = "previously.created.dataframe.2")
# method 1 with memory use of ~xMB?
big.object.1$recoded.column <- ifelse(big.object.1$old.column > 0,
big.object.1$recoded.column * 2,
big.object.1$recoded.column * 0.5)
# method 2 with memory use of ~2xMB?
new.column_function <- function(data, old.col, recoded.col)
data[recoded.col] <- ifelse(data[old.col] > 0,
data[recoded.col] * 2,
data[recoded.col] * 0.5)
new.column_function(data = big.object.1,
recoded.col = 400,
new.col = 401)
当代码很复杂但没有函数但内存是函数的问题时,最佳做法是什么?如何避免复制大对象?
【问题讨论】:
您可以尝试data.table
,当您的data.frame 存在内存问题时。:=
,快速添加、删除和更新列子集,参考。
@incas56,你能举一个简单的例子作为答案吗?甚至可能将 data.frame 转换为 data.table,然后按照上面指定的方式操作 data.table?谢谢。
【参考方案1】:
您可以使用<<-
(而不是<-
)在函数内访问全局环境中的对象
new.column_function <- function(old.col, recoded.col)
ind <- big.object[old.col] > 0
# Do this
big.object[recoded.col] <<- ifelse(ind, big.object[recoded.col][ind] * 2,
big.object[recoded.col][ind] * 0.5)
# OR do this
big.object[recoded.col][ind] <<- big.object[recoded.col][ind] * 2
big.object[recoded.col][!ind] <<- big.object[recoded.col][!ind] * 0.5
# Don't think this behaves in the intended way...
# ifelse(big.object[old.col] > 0,
# big.object[recoded.col] * 2,
# big.object[recoded.col] * 0.5)
我不知道这是否比使用data.table
更好。
【讨论】:
假设我有 big.object.1 和 big.object.2。因此,我认为我需要一个函数参数来指定哪个对象(例如 function(big.object, old.col, recoded.col) )。 如果我调用 new.column_function(big.object.2, 400, 401) 并在函数内部使用 ,这是否仍会避免复制 big.object.2?或者您可能建议 big.object.1 使用一个函数,而 big.object.2 使用第二个函数?new.column_function(big.object.2, 400, 401)
将创建big.object.2
的副本。顺便说一句,您的 ifelse 是错误的。
我觉得你使用ifelse
的方式有问题。尝试编辑后的解决方案中的一种方法。
如果您有类似的几个大对象要传递,然后尝试使用指标变量,然后执行if() else
确定要工作的对象。将名称作为刺痛传递也可以。【参考方案2】:
您可以尝试使用函数get
和assign
仅将对象的名称提供给函数而不是整个对象
new.column_function <- function(nameOfData, old.col, recoded.col)
get(nameOfData)[recoded.col] <- ifelse(data[old.col] > 0,
data[recoded.col] * 2,
data[recoded.col] * 0.5)
在这种情况下,nameOfData 是一个值为 big.object.1
的字符串,例如
【讨论】:
以上是关于要求 r 函数在全局环境中使用对象而不是对象的副本的主要内容,如果未能解决你的问题,请参考以下文章