5

这是我的问题。我有一个包含 200k 行的数据集。

  • 每行对应于对一个主题进行的测试。
  • 受试者的测试次数不等。
  • 每个测试都有日期。

我想为每个测试分配一个索引。例如,主题 1 的第一次测试将是 1,主题 1 的第二次测试将是 2。主题 2 的第一次测试将是 1,依此类推。

我的策略是获取唯一主题 ID 的列表,使用 lapply 将数据集子集到使用唯一主题 ID 的数据框列表中,每个主题都有他/她自己的数据框并进行测试。理想情况下,我将能够对每个主题的每个数据框进行排序并为每个测试分配一个索引。

但是,在 200k x 32 数据帧上执行此操作会使我的笔记本电脑(i5、Sandy Bridge、4GB 内存)很快耗尽内存。

我有两个问题:

  1. 有一个更好的方法吗?
  2. 如果没有,我克服内存限制的唯一选择是将我唯一的 SubjectID 列表分解为更小的集合,例如每个列表 1000 个 SubjectID,将其应用到数据集中,最后将列表连接在一起。然后,我如何通过提供一个表示分区数的整数来创建一个函数来破坏我的 SubjectID 列表。例如 BreakPartition(Dataset, 5) 将数据集平均分成 5 个分区。

这是生成一些虚拟数据的代码:

UniqueSubjectID <- sapply(1:500, function(i) paste(letters[sample(1:26, 5, replace = TRUE)], collapse =""))
UniqueSubjectID <- subset(UniqueSubjectID, !duplicated(UniqueSubjectID))
Dataset <- data.frame(SubID = sample(sapply(1:500, function(i) paste(letters[sample(1:26, 5, replace = TRUE)], collapse ="")),5000, replace = TRUE))
Dates <- sample(c(dates = format(seq(ISOdate(2010,1,1), by='day', length=365), format='%d.%m.%Y')), 5000, replace = TRUE)
Dataset <- cbind(Dataset, Dates)
4

2 回答 2

5

我猜想分裂/lapply 是什么耗尽了内存。您应该考虑一种更加矢量化的方法。从示例代码的略微修改版本开始:

n <- 200000
UniqueSubjectID <- replicate(500, paste(letters[sample(26, 5, replace=TRUE)], collapse =""))
UniqueSubjectID <- unique(UniqueSubjectID)
Dataset <- data.frame(SubID = sample(UniqueSubjectID , n, replace = TRUE))
Dataset$Dates <- sample(c(dates = format(seq(ISOdate(2010,1,1), by='day', length=365), format='%d.%m.%Y')), n, replace = TRUE)

并假设您想要的是按主题按日期顺序计算测试的索引,您可以执行以下操作。

Dataset <- Dataset[order(Dataset$SubID, Dataset$Dates), ]
ids.rle <- rle(as.character(Dataset$SubID))
Dataset$SubIndex <- unlist(sapply(ids.rle$lengths, function(n) 1:n))

现在“数据集”中的“子索引”列包含测试的按主题编号索引。这需要非常少的内存,并在我的 4GB Core 2 duo 笔记本电脑上运行几秒钟。

于 2012-05-16T08:41:30.563 回答
4

这听起来像是plyr包裹的工作。我会以这种方式添加索引:

require(plyr)
system.time(new_dat <- ddply(Dataset, .(SubID), function(dum) {
    dum = dum[order(dum$SubID, dum$Dates), ]
    mutate(dum, index = 1:nrow(dum))
  }))

这将数据集分成每个块SubID,并添加一个索引。新对象已将所有对象SubID组合在一起,并按时间排序。您的示例在我的机器上花费了大约 2 秒,并且几乎没有使用内存。我不确定如何ddply扩展到您的数据大小和特征,但您可以尝试。我这不够快,一定要看看data.table包装。我的一篇博文比较(除其他外)ddplydata.table可以作为一些灵感。

于 2012-05-16T08:39:00.517 回答