r - 在基本包中,如何在向量的两个副本之间生成唯一的无序对?
问题描述
给定 n=2,我想要一组值 (1, 1)、(1, 2) 和 (2, 2)。对于 n=3,我想要 (1, 1)、(1, 2)、(1, 3)、(2, 2)、(2, 3) 和 (3, 3)。对于 n=4、5 等,依此类推。
我想完全在基础库中做到这一点。最近,我开始使用
gen <- function(n)
{
x <- seq_len(n)
cbind(combn(x, 2), rbind(x, x))
}
这提供了一些可行但很老套的输出。对于 n = 4,我们得到以下结果。
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
x 1 1 1 2 2 3 1 2 3 4
x 2 3 4 3 4 4 1 2 3 4
有没有更好的办法?在expand.grid
、outer
、combn
和 R 的许多其他生成向量的方法之间,我希望能够只用一个组合生成函数来做到这一点,而不必将 的输出combn
与其他东西绑定在一起。我可以写出明显的for
循环,但这似乎是在浪费 R 的能力。
从开始expand.grid
然后子集是迄今为止许多答案所采用的一个选项,但我发现生成两倍的集合的想法是我需要的内存使用不当。这大概也排除了outer
。
解决方案
这里有一些方法可以做到这一点。
1)upper.tri
n <- 4
d <- diag(n)
u <- upper.tri(d, diag = TRUE)
rbind(row(d)[u], col(d)[u])
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 1 2 1 2 3 1 2 3 4
## [2,] 1 2 2 3 3 3 4 4 4 4
最后一行代码也可以写成:
t(sapply(c(row, col), function(f) f(d)[u]))
2) 梳理
n <- 4
combn(n+1, 2, function(x) if (x[2] == n+1) x[1] else x)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 1 1 1 2 2 2 3 3 4
## [2,] 2 3 4 1 3 4 2 4 3 4
这种变化是:
co <- combn(n+1, 2)
co[2, ] <- ifelse(co[2, ] == n+1, co[1, ], co[2, ])
co
3) 列表理解
library(listcompr)
t(gen.matrix(c(i, j), i = 1:n, j = i:n))
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 1 2 1 2 3 1 2 3 4
## [2,] 1 2 2 3 3 3 4 4 4 4
表现
library(microbenchmark)
library(listcompr)
n <- 25
microbenchmark(
upper.tri = {
d <- diag(n)
u <- upper.tri(d, diag = TRUE)
rbind(row(d)[u], col(d)[u]) },
upper.tri2 = {
d <- diag(n)
u <- upper.tri(d, diag = TRUE)
t(sapply(c(row, col), function(f) f(d)[u])) },
combn = combn(n+1, 2, function(x) if (x[2] == n+1) x[1] else x),
combn2 = {
co <- combn(n+1, 2)
co[2, ] <- ifelse(co[2, ] == n+1, co[1, ], co[2, ])
co
},
listcompr = t(gen.matrix(c(i, j), i = 1:n, j = i:n)))
给予:
Unit: microseconds
expr min lq mean median uq max neval cld
upper.tri 41.8 52.00 65.761 61.30 77.15 132.6 100 a
upper.tri2 110.8 128.95 187.372 154.85 178.60 3024.6 100 a
combn 1342.8 1392.25 1514.038 1432.90 1473.65 7034.7 100 a
combn2 687.5 725.50 780.686 765.85 812.65 1129.4 100 a
listcompr 97889.0 100321.75 106442.425 101347.95 105826.55 307089.4 100 b
推荐阅读
- excel - VBA - 创建字符串/哈希的唯一ID
- javascript - 表单动作不会被“必需的”输入打断
- node.js - TypeORM & PM2:无法在 Heroku 上运行应用程序
- javascript - Firestore orderBy timestamp desc 不起作用
- animation - 在 React Native 中通过用户触摸旋转光盘
- mongoose - 找不到模块“/Users/mymacbook/install”
- javascript - 使用 office.js 和加载项替换 PowerPoint 中的特定文本
- powershell - 无法使用 Powercli 检索“EsxCli”的“software.acceptance”值
- reactjs - 通过不同的id调用多个值
- python - QLabel 不会重新绘制像素图