1

我对 R 几乎是新手,很抱歉,如果我提出一些基本问题,但我找不到解决这个“简单”问题的方法:拥有一个包含患者的数据库(大数据库,2500 万行,14 列),我有几个每个“id”的行,例如以下结构:

"id" "birth_date"  "treatment"  "date_treatment"
123   2002-01-01    2            2011-01-03
123   2002-01-01    3            2011-10-03
124   2002-01-01    6            2009-11-07
124   2002-01-01    NA           NA
...   .....         ......       ........ 
1022  2007-01-01    4            2011-01-06

我必须使用 ff 包才能使用少量 RAM,因此所有进程都应该放入 ff 函数中。而且我想知道,对于每个单独的“id”,这是他/她接受治疗 = 2 或 4 时的最小“年龄”。所以,在每个单独的 id中,在通用代码中:

if(c(2,4) 中的治疗) 然后 min(date_treatment -birth_date)

我只想保留那些最小的“年龄”数据,也许还有 ID。

一种解决方案是:

age_c <- (data$date_treatment - data$birth_date)/365.25;
data$age_c <- age_c;
idx <- ffwhich( data, treatment %in% c(2,4) );
result  <- data[idx,];

这将所有进程保持在 ff 中,并且没有内存问题,但是......我仍然需要找到一种方法来为每个 id 获取这些最小年龄...... ffdfdply 似乎能够做到这一点:

age_fun <- function(x){ 
  min_ <- min.ff(x$age_c); 
  data.frame( age = min_);  
}

 result2 <- ffdfdply(x = data,
               split = data$id,
               FUN = function(x) age_fun(x),
               BATCHBYTES = 5000,
               trace=TRUE
 ); 

这需要很长时间,也给了我很多不同的错误....

有什么解决办法吗?
这是一个在 SAS 或 SQL 中很容易解决的普遍问题,但我在 R 中找不到正确的组合。所以一般问题是:

如何在非常大的数据集中计算变量(行)的相同值(组)的行列函数???

谢谢 !!

4

1 回答 1

2

ffdfdply 是您解决问题所需的功能,但您使用错误且效率低下。将 ffdfdply 视为进入每个 FUN,数据 R 的最大数量允许您放入 RAM,但仍确保您通过 RAM 中的每个 id 获取所有数据(或者如果它适合 RAM,则可能是多个 id)。

因此,使用 BATCHBYTES 5000 相当小(您真的只有 5 KB 的 RAM - 我猜不是 - 您是否在 90 年代的 Commodore 上安装了 R?)接下来,您的 FUN age_fun 写错了。要查看您在 FUN 中获得的内容,您可以将其打印出来。如 FUN=function(x){ print(head(x))); X}。在 FUN 中,您在 RAM 中获取数据,因此您不需要使用 min.ff,min 就可以了。

另请注意 joran 的评论:如果您的 RAM 允许,您会在每个块中获得多个 id。确保您的 FUN 执行拆分应用组合策略或在 FUN 中使用 dply。还有另一个加快速度的评论。你真的需要通过整个ffdf吗?您只需要在函数和拆分中使用的列。所以 ffdfdply(x = data[c("id","age_c","treatment")], split = ...) 会这样做,否则你会在 RAM 中获得不需要的数据。

简而言之,这样的事情就可以了

require(doBy)
result2 <- ffdfdply(
  x = data[c("id","age_c","treatment")], split = data$id,
  FUN = function(x) summaryBy(age_c ~ id, data=subset(x, treatment %in% c(2,4)), FUN=min))

如果您还想让您的人没有接受过治疗 2 和 4 什么的,请这样做。

require(doBy)
result2 <- ffdfdply(
  x = data[c("id","age_c","treatment")], split = data$id,
  FUN = function(x) {
   persons <- unique(x[, "id", drop=FALSE])
   result <- merge(
     persons,
     summaryBy(age_c ~ id, data=subset(x, treatment %in% c(2,4)), FUN=min),
     by.x="id", by.y="id", all.x=TRUE, all.y=FALSE
     )
   result
})
于 2012-11-15T22:31:47.113 回答