加快R中成对观察的计数

时间:2017-04-07 16:35:02

标签: r performance

我有一个数据集,其中每个条目的测量子集随机丢失:

dat <- matrix(runif(100), nrow=10)
rownames(dat) <- letters[1:10]
colnames(dat) <- paste("time", 1:10)
dat[sample(100, 25)] <- NA

我感兴趣的是计算此数据集中每行之间的相关性(即a-a,a-b,a-c,a-d,...)。但是,我想通过在得到的相关矩阵中将它们的值设置为NA来排除少于5个成对非NA观测值的相关性。

目前我这样做如下:

cor <- cor(t(dat), use = 'pairwise.complete.obs')
names <- rownames(dat)
filter <- sapply(names, function(x1) sapply(names, function(x2) 
    sum(!is.na(dat[x1,]) & !is.na(dat[x2,])) < 5))
cor[filter] <- NA

但是,此操作非常慢,因为实际数据集包含大于1,000个条目。

是否有办法根据非NA成对观察的数量以矢量化方式过滤细胞,而不是在嵌套循环中?

1 个答案:

答案 0 :(得分:1)

您可以使用矩阵方法计算非NA成对观察的数量。

让我们使用这个数据生成代码。我把数据做大了,增加了更多的NA。

nr = 1000;
nc = 900;
dat = matrix(runif(nr*nc), nrow=nr)
rownames(dat) = paste(1:nr)
colnames(dat) = paste("time", 1:nc)
dat[sample(nr*nc, nr*nc*0.9)] = NA

然后你过滤代码需要85秒

tic = proc.time()
names = rownames(dat)
filter = sapply(names, function(x1) sapply(names, function(x2) 
    sum(!is.na(dat[x1,]) & !is.na(dat[x2,])) < 5));
toc = proc.time();
show(toc-tic);
# 85.50 seconds

我的版本为原始数据中的非NA创建了一个值为1的矩阵。然后使用矩阵乘法我计算成对非NA的数量。它只用了不到一秒钟。

tic = proc.time()
NAmat = matrix(0, nrow = nr, ncol = nc)
NAmat[ !is.na(dat) ] = 1;
filter2 = (tcrossprod(NAmat) < 5)
toc = proc.time();
show(toc-tic);
# 0.09 seconds

简单检查显示结果相同:

all(filter == filter2)
# TRUE