我有一个庞大的数据框:
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))
这个过程需要很多时间。 我想知道是否有更有效的方法来做到这一点?
答案 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))
}