将字符串列表分解为分区

时间:2012-05-16 07:59:01

标签: r subset plyr data.table

这是我的问题。我有一个20万行的数据集。

  • 每行对应于对主题进行的测试。
  • 受试者的测试次数不等。
  • 每项测试都已过时。

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

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

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

我有两个问题:

  1. 有更好的方法吗?
  2. 如果没有,我唯一的选择是克服内存限制是将我的唯一SubjectID列表分成较小的集合,例如每个列表1000个SubjectID,通过数据集提供它,并在所有内容的末尾将列表连接在一起。然后,如何创建一个函数来打破我的SubjectID列表,方法是提供一个表示分区数的整数。例如BreakPartition(数据集,5)将数据集平均分成5个分区。
  3. 以下是生成一些虚拟数据的代码:

    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)
    

2 个答案:

答案 0 :(得分: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))

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

答案 1 :(得分: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进行比较的blog post of mine可以作为一些灵感。