R-是否有一种矢量化方法/预制函数可以快速生成两个矢量之间的唯一集?
所以,我想要的是一个数据帧,其中两个随机向量的组合在行上表示。我不想要像这样的重复组合;1,2;2,1. 只有一个。以及不重复的组合;1,1 现在我得到了这个简单的for循环,但它并不理想R-是否有一种矢量化方法/预制函数可以快速生成两个矢量之间的唯一集?,r,performance,unique,vectorization,combinations,R,Performance,Unique,Vectorization,Combinations,所以,我想要的是一个数据帧,其中两个随机向量的组合在行上表示。我不想要像这样的重复组合;1,2;2,1. 只有一个。以及不重复的组合;1,1 现在我得到了这个简单的for循环,但它并不理想 unique_combos <- function(v1, v2) { df <- data.frame(matrix(ncol=2)) counter = 0 for (name1 in v1) { for (name2 in v2) {
unique_combos <- function(v1, v2) {
df <- data.frame(matrix(ncol=2))
counter = 0
for (name1 in v1) {
for (name2 in v2) {
if (name1 != name2){
counter = counter + 1
df[counter,] <- c(name1, name2)
}
}
}
return(df)
}
# example usage;
> v1 <- c(1,2,3,4)
> v2 <- c(3,4,5,6)
> unique_combos(v1, v2)
X1 X2
1 1 3
2 1 4
3 1 5
4 1 6
5 2 3
6 2 4
7 2 5
8 2 6
9 3 4
10 3 5
11 3 6
12 4 3
13 4 5
14 4 6
>
unique_组合根本不需要循环。
您可以使用expand.grid
并在一条指令中包含data.frame和repeats。然后使用逻辑索引只保留不同的行
unique_combos2 <- function(v1, v2) {
e <- expand.grid(v1, v2)
e <- e[e[[1]] < e[[2]], ]
e[order(e[[1]]), ]
}
u1 <- unique_combos(v1, v2)
u2 <- unique_combos2(v1, v2)
这里的速度差可能不会有任何实际影响,除非向量很大,但是因为你把“性能”作为标签,这里有一个稍微快一点的方法
library(data.table)
CJ(v1, v2)[V1 != V2]
基准:
注:
默认情况下,CJ
将按v1
订购,而在unique_combos2
中按v1
订购需要花费大量时间,因此我删除了该部分,因为不清楚您是否需要它
unique_combos2 <- function(v1, v2) {
e <- expand.grid(v1, v2)
e <- e[e[[1]] != e[[2]], ]
e
}
unique_combos3 <- function(v1, v2) CJ(v1, v2)[V1 != V2]
w1 <- sample(200)
w2 <- sample(200)
mb2 <- microbenchmark(
u2 = unique_combos2(w1, w2),
u3 = unique_combos3(w1, w2)
)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# u2 5.513842 5.942765 10.969386 6.692507 8.158763 368.180211 100 b
# u3 1.140513 1.443076 1.898202 1.711384 2.139075 8.397942 100 a
这里有一个tidyverse
方法,主要使用purr
工具。(编辑以澄清问题)。此方法执行以下操作:
获取向量乘积集的列表,过滤它们相等的情况
将列表元素转换为已排序的整数向量,并丢弃所有重复的unique
将
转换回列列表结构,简化
将列转换为向量,并放回数据帧中
非常开放,看看是否有人能想出一种方法来浓缩一些步骤
v1%
唯一%>%
转置(.names=c(“x”,“y”))%>%
简化所有%>%
作为_tible()
#>#A tibble:13 x 2
#>xy
#>
#> 1 1 3
#> 2 2 3
#> 3 3 4
#> 4 1 4
#> 5 2 4
#> 6 1 5
#> 7 2 5
#> 8 3 5
#> 9 4 5
#> 10 1 6
#> 11 2 6
#> 12 3 6
#> 13 4 6
由(v0.2.0)于2018-10-05创建。我编辑了我的帖子,组合不对!参见3-4-3组合。我想避免这种行为,只使用1而不是两者。@CasperPetersBerghopper现在是Frank使用的想法。我编辑了我的帖子,组合不对!参见3-4-3组合。我想避免这种行为,只需要1而不是两者。不,我不需要v1的精确顺序,我只需要combinations@Caspar我想用
或@Frank谢谢!现在一切都像我希望的那样工作:)。我不明白为什么这样做有效,你能解释一下为什么使用
或解决方案使用
或哦,好的,Ryan。另一个选择是unique(CJ(v1,v2)[v1>v2,c(“v1”,“v2”):=(v2,v1)])
@Caspar它通过选择一个约定来工作(至少在后一个公式中),这样就可以保留成对的v1v2。嗨,我编辑了我的帖子,谢谢你指出仍然存在的组合(我的错误)。我不一定需要订购,我只需要独特的组合。澄清;是的,我只想要其中一个组合,不管是哪一个。编辑以解决此澄清!
library(data.table)
CJ(v1, v2)[V1 != V2]
unique_combos2 <- function(v1, v2) {
e <- expand.grid(v1, v2)
e <- e[e[[1]] != e[[2]], ]
e
}
unique_combos3 <- function(v1, v2) CJ(v1, v2)[V1 != V2]
w1 <- sample(200)
w2 <- sample(200)
mb2 <- microbenchmark(
u2 = unique_combos2(w1, w2),
u3 = unique_combos3(w1, w2)
)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# u2 5.513842 5.942765 10.969386 6.692507 8.158763 368.180211 100 b
# u3 1.140513 1.443076 1.898202 1.711384 2.139075 8.397942 100 a
unique(CJ(v1, v2)[V1 > V2, c("V1", "V2") := .(V2, V1)])