给定两个数组:
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 的派生词来完成此操作吗?
而不是mapply
我会为矢量化函数使用 R 内部回收规则。如果a
和b
是相同的长度,你只需要这样做:
as.integer( a < b )
#[1] 1 0 0
as.integer
只是在那里强制1
or 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
我最初阅读“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
我偶然发现了“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