【问题标题】:Using apply family functions when loop over arguments in a function in r在 r 中的函数中循环参数时使用应用族函数
【发布时间】:2016-02-12 11:25:18
【问题描述】:

如何使用应用类型函数之一循环函数中的参数以使 R 中的代码更快?例如,我创建了一个函数来计算三个随机变量的联合互信息

### Function to loop over: Joint Mutual Information I({x_1,x_2};y)
library(infotheo)
JMI <-function(x1,x2,y){
      entropy(cbind(x1,x2),method="emp") + entropy(y, method="emp") - 
      entropy(cbind(x1,x2,y),method="emp")
   } 

假设我有两个矩阵 (x1, x2) 和一个向量 y,例如:

#### randomly generate binary variables from a bernoulli distribution
set.seed(12345)
f1 <- rbinom(n=300,size=1,prob=0.5)
f2 <- rbinom(n=300,size=1,prob=0.5)
f3 <- rbinom(n=300,size=1,prob=0.5)

## creat y using xor operation of the two feature: x1 XOR x2
#  this mean that y is 1 if f1[i]!=f2[i] and 0 otherwise
y <- ifelse(f1==f2,0,1)
x1 <-cbind(f1,f2)
x2 <- cbind(x1,f3)

现在,我想在 JMI 函数中循环 x1 和 x2。使用 for 循环看起来像这样:

# a length(x1) x length(x2)-Matrix with zeros
jmi <- matrix(rep(0,ncol(x2)*ncol(x1)),
          nrow=ncol(x1),ncol=ncol(x2))
#### For loops to be avoided
for(i in 1:ncol(x1)){
  for(j in 1:ncol(x2)){
    jmi[i,j] <- JMI(x1[,i],x2[,j],y)
  }#end out for(j)
}#end inner for(i)

有没有一种简单的方法可以避免两个 for 循环?

【问题讨论】:

  • 我认为您在最后一个代码部分中混淆了行和列。当你定义jmi时,你使用nrow = ncol(x2),但是在循环中,行索引i会超过1:ncol(x1)
  • 编辑不够。现在问题出现在对JMI 的调用中:i 运行在x2 的列上,但用于获取x1 的列(反之亦然)。请在发布之前运行您的代码。一旦你发布了一个工作示例,我会更新我的解决方案。
  • 很抱歉,代码在我的电脑上运行良好。 i 在 x1 的列上运行并在 x1 中使用,对于 x2 也是如此
  • 在您最后一次编辑之后,它确实运行良好。感谢您的更正。

标签: r performance for-loop apply mapply


【解决方案1】:

这是一个使用 apply 的解决方案:

g <- expand.grid(1:ncol(x1), 1:ncol(x2))
v <- apply(g, 1, function(i) JMI(x1[, i[1]], x2[, i[2]], y))
jmi <- matrix(v, nrow = ncol(x1))
jmi
##             [,1]        [,2]       [,3]
## [1,] 0.003809514 0.693147181 0.01082319
## [2,] 0.693147181 0.006485284 0.01152807

它分三个步骤进行:

  • x1x2 矩阵列的索引是使用expand.grid 创建的。这将创建一个数据框 g,其中两列包含您的 for 循环所经过的 ij 的所有组合。
  • 然后apply用于遍历g的所有行,并将JMI应用于x1x2的对应列。这会产生一个向量 v
  • 最后,v 被转换为矩阵。

【讨论】:

  • 有效!非常感谢!
  • 太好了,我很高兴它有帮助。您能否更新您的问题,以便您的示例代码实际上正在运行?然后,我将确保问题与更新后的答案相符。
  • 是的,它可以工作,但不幸的是它似乎并不比两个 for 循环快。
  • 没有理由期望它会更快。
  • 好吧,但我尽量避免使用 for 循环的唯一原因是因为速度很慢。如果这里的 apply() 解决方案并不比使用它的速度快多少?
猜你喜欢
  • 2017-05-03
  • 2017-09-09
  • 1970-01-01
  • 2022-10-21
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多