从大型相关矩阵中提取唯一对

Mar*_*ius 2 r matrix duplicates large-data

我有一个相当大的数据集(约 50K 条目),我用它来生成相关矩阵。这效果很好,“仅”使用约 20GB RAM。

然后,我想从中提取唯一的成对组合并将其转换为数据框。这就是我遇到问题的地方。RAM 使用量过多或索引变量溢出。我知道有 >2B 的组合,所以我知道它的大小有点爆炸,但仍然..

我尝试了不同的方法来实现这一目标,但没有成功。

模拟数据:

df = matrix(runif(1),nrow=50000, ncol=50000, dimnames=list(seq(1,50000,by=1), seq(1,50000,by=1)))
Run Code Online (Sandbox Code Playgroud)

尝试从相关矩阵中提取上/下三角形,然后重塑它:

df[lower.tri(df, diag = T),] = NA
df = reshape2::melt(df, na.rm = T)
Run Code Online (Sandbox Code Playgroud)

崩溃:

Error in df[lower.tri(bla, diag = T), ] = NA : 
  long vectors not supported yet: ../../src/include/Rinlinedfuns.h:522
Run Code Online (Sandbox Code Playgroud)

如果您只执行以下操作,它会因相同的错误而崩溃:(df = df[lower.tri(df, diag = T),] 我确实阅读了R 中的大型矩阵:尚不支持长向量,但我发现它对我的情况没有帮助)

我也尝试过:

df = subset(as.data.frame(as.table(df)),
       match(Var1, names(annotation_table)) > match(Var2, names(annotation_table)))
Run Code Online (Sandbox Code Playgroud)

仅使用基于 R 的软件包,但最终在大约 1 天后耗尽了内存。这是 RAM 最密集的部分:as.data.frame(as.table(df))所以我也尝试用它替换它reshape2::melt(df),但它也耗尽了 RAM

我在具有 128GB RAM 的 Ubuntu 机器上运行代码。我确实有更大的机器,但我希望这个内存量应该足够了。

任何帮助将不胜感激。谢谢。

Mik*_*gan 6

n如果你有像你所说的那样多的 RAM,那么对于大于 6 的内存来说,这确实应该可以正常工作。

set.seed(0)
n <- 6L
x <- provideDimnames(cor(matrix(rnorm(as.double(n) * n), n, n)))
x
Run Code Online (Sandbox Code Playgroud)
            A           B            C           D           E            F
A  1.00000000  0.42679900  0.113100027 -0.03952030 -0.02406114 -0.693427730
B  0.42679900  1.00000000  0.519377903  0.06136646 -0.51713799 -0.331961466
C  0.11310003  0.51937790  1.000000000 -0.43996491 -0.32225557 -0.006199606
D -0.03952030  0.06136646 -0.439964909  1.00000000 -0.42053358  0.537301520
E -0.02406114 -0.51713799 -0.322255571 -0.42053358  1.00000000 -0.367595700
F -0.69342773 -0.33196147 -0.006199606  0.53730152 -0.36759570  1.000000000
Run Code Online (Sandbox Code Playgroud)
s <- seq_len(n) - 1L
nms <- dimnames(x)
dat <- data.frame(val = x[sequence(s, seq.int(1L, length(x), n))],
                  row = gl(n, 1L, labels = nms[[1L]])[sequence(s, 1L)], 
                  col = rep.int(gl(n, 1L, labels = nms[[2L]]), s))
dat
Run Code Online (Sandbox Code Playgroud)
            val row col
1   0.426798998   A   B
2   0.113100027   A   C
3   0.519377903   B   C
4  -0.039520302   A   D
5   0.061366463   B   D
6  -0.439964909   C   D
7  -0.024061141   A   E
8  -0.517137993   B   E
9  -0.322255571   C   E
10 -0.420533577   D   E
11 -0.693427730   A   F
12 -0.331961466   B   F
13 -0.006199606   C   F
14  0.537301520   D   F
15 -0.367595700   E   F
Run Code Online (Sandbox Code Playgroud)

如果您使用的 R 版本早于 4.0.0,其中sequence定义不同,那么您将需要类似以下内容的内容:

sequence <- function(nvec, from = 1L, by = 1L)
    unlist(.mapply(seq.int, list(from = from, by = by, length.out = nvec), NULL),
           recursive = FALSE, use.names = FALSE)
Run Code Online (Sandbox Code Playgroud)

请注意,如果确定结果将溢出,seq.int则接受integerdouble参数,并且方便地返回 adouble而不是 an ,在本例中发生了溢出。integerintegern * n > .Machine$integer.max

M <- .Machine$integer.max
typeof(seq.int(from = 1L, to = 1 + M, by = M))
Run Code Online (Sandbox Code Playgroud)
[1] "double"
Run Code Online (Sandbox Code Playgroud)