R—选择满足多个条件的矩阵行的最快方法
这是对R中问题的扩展。假设我有矩阵:R—选择满足多个条件的矩阵行的最快方法,r,performance,matrix,conditional-statements,multiple-columns,R,Performance,Matrix,Conditional Statements,Multiple Columns,这是对R中问题的扩展。假设我有矩阵: one two three four [1,] 1 6 11 16 [2,] 2 7 12 17 [3,] 3 8 11 18 [4,] 4 9 11 19 [5,] 5 10 15 20 [6,] 1 6 15 20 [7,] 5 7 12 20 我想返回所有行,其中矩阵$two==7和矩阵$two==1
one two three four
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 11 18
[4,] 4 9 11 19
[5,] 5 10 15 20
[6,] 1 6 15 20
[7,] 5 7 12 20
我想返回所有行,其中矩阵$two==7
和矩阵$two==12
。这就是我知道的方法:
out <- mat[mat$two == 7,]
final_out <- out[out$three == 12, ]
out使用which
和arr.ind=TRUE
如中所示:
> mat[which(mat[,"two"]==7 & mat[,"three"] == 12, arr.ind = TRUE),]
one two three four
2 2 7 12 17
7 5 7 12 20
只需使用带有逻辑比较的[
子集设置
# Reproducible data
set.seed(1)
m <- matrix( sample(12,28,repl=T) , 7 , 4 )
[,1] [,2] [,3] [,4]
[1,] 4 8 10 3
[2,] 5 8 6 8
[3,] 7 1 9 2
[4,] 11 3 12 4
[5,] 3 3 5 5
[6,] 11 9 10 1
[7,] 12 5 12 5
# Subset according to condition
m[ m[,2] == 3 & m[,3] == 12 , ]
[1] 11 3 12 4
#可复制数据
种子(1)
mR中绝对最快的方法是ifelse
,这与if
不同,if
允许向量化条件。您还可以缓存条件向量(例如isSeven使用微基准更新:
使用基准测试给出了相反的答案。@SimonO101给出的答案似乎提供了一个稍微快一点的实现
require(microbenchmark)
set.seed(1)
m <- matrix( sample(12,100,repl=T) , 25 , 4 )
colnames(m) <- c("one","two","three","four")
bench1 <- microbenchmark(m[which(m[,'two']==7 & m[,'three'] == 12, arr.ind = TRUE),])
summary(bench1$time)
Min. 1st Qu. Median Mean 3rd Qu. Max.
7700 8750 9449 9688 9800 22400
bench2 <- microbenchmark(m[ m[,2] == 3 & m[,3] == 12 , ])
summary(bench2$time)
Min. 1st Qu. Median Mean 3rd Qu. Max.
6300 7350 7351 7599 8050 15400
require(微基准)
种子(1)
m如果有很多行,那么最好还是先进行子集,如下面的代码所示
set.seed(1)
m <- matrix( sample(12,28,repl=T) , 12e6 , 4 )
# Subset according to condition
microbenchmark(sample0=m[ m[,2] == 3 & m[,3] == 12 , ],times = 10L)
microbenchmark(sample1=m[ m[,2] == 3, ],
sample2= sample1[sample1[,3] == 12, ],times = 10L)
或mat[mat[,“two”]==7&mat[,“two”]==12,]
我没有完全阅读这个问题,也没有意识到OP已经使用了哪个是适合矩阵的$sub设置?我得到了一个错误。我认为ifelse
不会比逻辑subsetting快。毕竟,这正是ifelse
内部所做的。你应该使用库(microbenchmark)
用于计算时间……它更可靠。@Thomas谢谢你的提示。这是我第一次尝试基准测试。我将在安装软件包后更新答案。这可能需要一点时间……环顾四周,你会看到人们如何使用它的其他示例。
set.seed(1)
m <- matrix( sample(12,1000000000,repl=T) , 1e8 , 10 )
colnames(m) <- c("one","two","three","four","five","six","seven","eight","nine","ten")
system.time(m[which(m[,'two']==7 & m[,'three'] == 12, arr.ind = TRUE),])
user system elapsed
6.49 1.58 8.06
system.time(m[ m[,2] == 3 & m[,3] == 12 , ])
user system elapsed
8.23 1.29 9.52
set.seed(1)
m <- matrix( sample(12,28,repl=T) , 12e6 , 4 )
# Subset according to condition
microbenchmark(sample0=m[ m[,2] == 3 & m[,3] == 12 , ],times = 10L)
microbenchmark(sample1=m[ m[,2] == 3, ],
sample2= sample1[sample1[,3] == 12, ],times = 10L)
microbenchmark(sample0=m[ m[,2] == 3 & m[,3] == 12 , ],times = 10L)
Unit: milliseconds
expr min lq mean median uq max neval
sample0 342.085212 347.333083 381.6039635 349.920741 375.383425 584.068743 10
microbenchmark(sample1=m[ m[,2] == 3, ],
sample2= sample1[sample1[,3] == 12, ],times = 10L)
Unit: milliseconds
expr min lq mean median uq max neval cld
sample1 188.647995 189.832552 215.9355769 194.2375715 199.118962 404.631420 10 b
sample2 5.097811 5.262028 5.3260160 5.2868025 5.401471 5.571351 10 a