【问题标题】:Require r function to use objects in global environment rather than copy of object要求 r 函数在全局环境中使用对象而不是对象的副本
【发布时间】: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?谢谢。

标签: r function memory large-data


【解决方案1】:

您可以使用&lt;&lt;-(而不是&lt;-)在函数内访问全局环境中的对象

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】:

您可以尝试使用函数getassign 仅将对象的名称提供给函数而不是整个对象

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 的字符串,例如

【讨论】:

    猜你喜欢
    • 2019-12-16
    • 2022-01-04
    • 1970-01-01
    • 2018-10-27
    • 2022-11-02
    • 1970-01-01
    • 2016-12-08
    • 2012-04-24
    • 1970-01-01
    相关资源
    最近更新 更多