在R中应用函数会导致内存分配错误

时间:2012-08-09 20:40:28

标签: r data.table

我正在尝试对 R 中数据框的每一行进行计算,并将计算作为新列添加到框架中。我开始使用“by”函数,但是计算速度非常慢,所以我转而使用“apply”函数。我想象它的工作方式是运行apply with my function,将输出保存到变量并将该数据附加到原始数据框。

我创建了一个函数来计算保险计划的期限长度并返回该值,该值在样本数据集上正常工作。当我使用我更大的数据集时,我收到“无法分配大小的矢量......”的错误。我知道很多人建议获得更多内存,但我已经有16GB的内存,并且整个数据集加载在 R 我的计算机上说它只使用了7.7GB的内存。数据集有44列,大约有1100万条记录,所以我没看到如何再添加一列数据占用8GB内存?

正确方向的任何一点都会很棒。


以下是我正在使用的功能:

get_term_length <- function(row_data){

    # convert values to dates
    expiration_date <- as.Date( row_data[42] )
    start_date <- as.Date( row_data[43] )
    cancellation_date <- as.Date( row_data[44] )

    # check to see if the cancellation date is NA - just use entire policy length
    if( is.na(cancellation_date) ){
        return( expiration_date - start_date) )
    }

    # check to see if policy was cancelled early
    if(cancellation_date < expiration_date){
        return( cancellation_date - start_date )
    }

    # the policy was for the entire term
    else{
        return( expiration_date - start_date )
    }

}

我一直在通过调用

来运行该函数
tmp <- apply(policy_data, 1, get_term_length)

3 个答案:

答案 0 :(得分:5)

@Dwin提示的data.table解决方案

 library(data.table)
 policy_data <- as.data.table(policy_data)

  # set the date  columns to be  IDate (the exact form of this will depend
  # on the format they are currently in

  policy_data[, cancellation_date := as.IDate(cancellation_date)]
  policy_data[, start_date := as.IDate(start_date)]
  policy_data[, end_date := as.IDate(end_date)]
  # create a column which is an indicator for NA 

  policy_data[, isna := is.na(cancellation_date)]


  setkey(policy_data, isna)

  policy_data[J(TRUE), tmp := expiration_date - start_date]
  policy_data[J(FALSE), tmp := pmin(cancellation_date - start_date, expiration_date-start_date)]   

答案 1 :(得分:4)

“经验法则”是您需要_at_least_ 连续 RAM的3倍作为您正在使用的最大对象,因此您可能需要更频繁地重新启动并限制数量您系统上其他正在运行的应用程序。我很高兴我的硬件有32 GB,我正在研究基于5-6 GB大小的数据对象的回归模型。

(我也常常对添加一列数据所花费的时间不满意,因此我有时会创建'外部'或'并行'向量,通常使用ave()函数进行表操作。或者我使用子集() - s的数据。)R大师正在研究这个问题,但尚未公布解决方案。 Matthew Dowle开发了'data.table'软件包来解决它(并且速度非常快),代价是“[”操作需要不同的语义。

您可以在此处找到讨论内存要求的其他帖子。投票最频繁的可能是: Tricks to manage the available memory in an R session。我有点惊讶的是,在那里的答案中没有提到data.table包。

编辑:我看到了您接受的答案(这实际上是使用数据子集的实例),但我认为这与您之前获得的结果不同。要获得该结果,您需要以下内容:

tmp <- with(policy_data, 
          ifelse( is.na(cancellation_date), expiration_date - start_date , # else
            pmin(as.Date(cancellation_date)-as.Date(start_date),
                 as.Date(expiration_date)-as.Date(start_date)
                 ))

如果您希望pmin功能正常运行,则不希望在ifelse中使用“na.rm = TRUE”。

答案 2 :(得分:3)

看起来你不需要整个data.frame。只需提取您需要的3列,就可以恢复大部分记忆。

tmp <- with(policy_data, 
            pmin(as.Date(cancellation_date)-as.Date(start_date),
                 as.Date(expiration_date)-as.Date(start_date),
                 na.rm=TRUE))