在R中将集合转换为列索引的有效方法是什么?

时间:2012-10-23 19:15:47

标签: performance algorithm r indexing set

概述

给一个大的(nrows> 5,000,000+)数据框 A ,包含字符串行名和不相交集列表(n = 20,000+), B ,其中每一组都包含来自 A 的行名称,通过唯一值创建表示 B 中的集合的向量的最佳方法是什么?

插图

以下是说明此问题的示例:

# Input
A <- data.frame(d = rep("A", 5e6), row.names = as.character(sample(1:5e6)))
B <- list(c("4655297", "3177816", "3328423"), c("2911946", "2829484"), ...) # Size 20,000+

期望的结果是:

# An index of NA represents that the row is not part of any set in B.
> A[,"index", drop = F]
        d index
4655297 A     1
3328423 A     1
2911946 A     2
2829484 A     2
3871770 A    NA
2702914 A    NA
2581677 A    NA
4106410 A    NA
3755846 A    NA
3177816 A     1

天真的尝试

使用以下方法可以实现这样的目的。

n <- 0
A$index <- NA
lapply(B, function(x){
  n <<- n + 1
  A[x, "index"] <<- n
})

问题

然而,由于多次索引A并且不是R-esque或优雅,这是非常慢的(几个小时)。

如何以快速有效的方式生成所需的结果?

1 个答案:

答案 0 :(得分:4)

以下建议使用与现有方法相比并不太糟糕的基础。

示例数据:

A <- data.frame(d   = rep("A", 5e6),
                set = sample(c(NA, 1:20000), 5e6, replace = TRUE),
                row.names = as.character(sample(1:5e6)))
B <- split(rownames(A), A$set)

基本方法:

system.time({
A$index <- NA
A[unlist(B), "index"] <- rep(seq_along(B), times = lapply(B, length))
})
#    user  system elapsed 
#   15.30    0.19   15.50 

检查:

identical(A$set, A$index)
# TRUE

对于任何更快的事情,我认为data.table会派上用场。