从巨大的数据框中选择元素的更有效方法

时间:2014-08-19 17:38:15

标签: r

我有一个庞大的数据框:

library(gtools)
a<-permutations(2,20,v=c(0,1),repeats.allowed=TRUE)
a<-as.data.frame(a)

我有100个随机字符串:

set.seed(123)

b<-replicate(100,sample(c(0,1),20, replace=T))

我想在'a'中找出与'b'中每列相对应的行号。

由于'a'很大,这个过程需要相当长的时间。

现在我正在使用以下方法:

sapply(1:100, function(x)  which(colSums(t(a)==as.numeric(b[,x]))==20L))

这个过程需要很多时间。 我想知道是否有更有效的方法来做到这一点?

1 个答案:

答案 0 :(得分:2)

通过将列视为位字符串将列表示为数字,然后使用%in%进行快速查找

library(gtools)
a <- permutations(2,20,v=c(0,1),repeats.allowed=TRUE)
a <- as.data.frame(a)

set.seed(123)
b <- replicate(100, sample(c(0, 1), 20, replace=TRUE))

a1 <- colSums(t(a) * 2^(0:19))
b1 <- colSums(b * 2^(0:19))

产生

> head(which(a1 %in% b1))
[1]  1191  9434 14502 19812 30619 34313

要处理重复项,请考虑这个较小的示例

b1 <- c(1, 3, 3, 5, 4)
a1 <- c(3, 4, 8)

发现唯一的b1值,并创建一个列表,将唯一值映射到原始值中的索引

ub1 <- unique(b1)
umap <- unname(split(seq_along(b1), match(b1, ub1)))

现在将a1与唯一的b1匹配,决定保留哪些(不是NA),并在唯一地图中查找匹配

m <- match(a1, ub1)
keep <- which(!is.na(m))
keepmap <- umap[m[keep]]

最后,使用keepmap计算每个保存值需要复制的次数(因为它映射到多个原始值)并创建结果的data.frame

len <- sapply(keepmap, length)
data.frame(ai=rep(keep, len),
           a1=rep(a1[keep], len),
           b1=unlist(unname(keepmap)))

所以完整的功能是

matchrows <-
    function(a, b)
{
    ## encode
    a1 <- colSums(t(a) * 2^(0:19))
    b1 <- colSums(b * 2^(0:19))

    ## match to unique values
    ub1 <- unique(b1)
    m <- match(a1, ub1)
    keep <- which(!is.na(m))

    ## expand unique matches to original coordinates
    umap <- unname(split(seq_along(b1), match(b1, ub1)))
    keepmap <- umap[m[keep]]

    len <- sapply(keepmap, length)
    data.frame(ai=rep(keep, len),
               bi=unlist(unname(keepmap)),
               value=rep(a1[keep], len))
}