1

给定两个数组:

a = array(1:3)
b = array(3:1)

我想应用一个函数,依次将 A 的每个元素的值与 B 的每个元素进行比较,并返回结果。

就像是:

compare = function(xa, xb) { if (xa < xb) { 1 } else { 0 } }

...其中 xa 将是 a 数组中的一个元素,而 xb 将是 b 数组中的一个元素。

我可以使用 apply 的派生词来完成此操作吗?

4

3 回答 3

7

而不是mapply我会为矢量化函数使用 R 内部回收规则。如果ab是相同的长度,你只需要这样做:

as.integer( a < b )
#[1] 1 0 0

as.integer只是在那里强制1or 0,实际上TRUE并且FALSE将在任何后续的乘法运算中表现1得如此。0

例子

set.seed(1); a <- sample(10)
#[1]  3  4  5  7  2  8  9  6 10  1

set.seed(2); b <- sample(10)
#[1]  2  7  5 10  6  8  1  3  4  9

a < b
#[1] FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE

a * ( a < b )
#[1] 0 4 0 7 2 0 0 0 0 1

a[ a < b ]
#[1] 4 7 2 1

有些人可能会感到惊讶,但<它是一个函数。它调用文件中调用的底层C函数(所有逻辑比较器都这样做 - 它们只是使用不同的开关进行比较类型)来处理向量回收。你可以这样写:do_relop/src/main/relop.c<

`<`( a , b )
#[1] FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE

基准测试

使用原始运算符(在一对长度为 1e6 的向量上)比使用它也是一个向量化函数<快 100 倍以上:ifelse

set.seed(1); a <- sample(10,1e6,repl=T)
set.seed(2); b <- sample(10,1e6,repl=T)
require( microbenchmark)
bm <- microbenchmark( comparealt(a,b) , `<`(a,b) , times = 25L )
print( bm , digits = 3 , unit = "relative" , order = "median" )
#Unit: relative
#             expr min  lq median  uq  max neval
#            a < b   1   1      1   1  1.0    25
# comparealt(a, b) 131 126    122 105 48.3    25
于 2013-09-06T16:14:05.710 回答
1

我最初阅读“A的每个元素到B的每个元素的值”表示外部连接并建议:

compare <- function(x, y){ outer(x, y, FUN="<")+0 }

例如给出

> compare(array(1:6), array(5:3))
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    1    1    1
[3,]    1    1    0
[4,]    1    0    0
[5,]    0    0    0
[6,]    0    0    0

为了比较相同维度的矩阵元素,你可以使用类似的东西

comparemat <- function(mat1, mat2){ (mat1 < mat2)+0 }

或者

comparealt <- function(mat1, mat2){ ifelse(mat1 < mat2, 1, 0) }

其中任何一个

comparemat(matrix(1:12,nrow=4), matrix(12:1,nrow=4)) 
comparealt(matrix(1:12,nrow=4), matrix(12:1,nrow=4)) 

     [,1] [,2] [,3]
[1,]    1    1    0
[2,]    1    1    0
[3,]    1    0    0
[4,]    1    0    0
于 2013-09-06T19:07:28.833 回答
0

我偶然发现了“mapply”,这似乎可以解决问题:

> gg = function(x,y){ if(x < y) { 1 } else { 0 }}
> gg(1,2)
[1] 1
> gg(2,1)
[1] 0
> mapply(gg, 1:4, 4:1)
[1] 1 1 0 0
于 2013-09-06T15:57:47.817 回答