【问题标题】:Replacing for loop with foreach loop用 foreach 循环替换 for 循环
【发布时间】:2023-07-25 07:57:01
【问题描述】:

我想并行化我的代码,以便我可以利用所有内核。因此,我想用 foreach 循环替换 for 循环。由于我是 R 的初学者,我无法理解关于这个主题的不同帖子如何解决这个问题。如果有人可以逐步帮助我,那就太好了(在每一行中发布 cmets,以便我理解它)。下面是我的 for 循环,我想用 foreach 替换它:

# A function used for Janshon-Shanon-Divergence computation, that I use inside my nested for loop
JensShanDiver = function(a,b) {
        m = 0.5 * (a + b)
        LRa = ifelse(a > 0, log2(a/m), 0)
        LRb = ifelse(b > 0, log2(b/m), 0)
        JSD = 0.5 * (sum(a * LRa) + sum(b * LRb))
        return(JSD)
}

#an empty dataframe having same dimensions as input dataframe
output <- data.frame(matrix(NA, nrow = nrow(input), ncol = ncol(input)))

#a vector of same length as of each row in input dataframe
v2 <- numeric(length(input[1,]))

for (j in 1:nrow(input)){
  #take each row from input df
   v1 <- as.numeric(input[j,])
   for(i in 1:length(v1)){
  # update an index value in the initially defined vector
    v2[i] <- 1
  # Take the sum of both vectors
    ifelse(v1[i] == 0, output_vec <- 1, output_vec <- JensShanDiver(v1, v2))
  # Reset the updated index to 0 again
    v2[i] <- 0
  # write the output value at [j,i]th index in the output dataframe 
    output[j,i] <- output_vec
   }
 }

输入数据帧示例如下:

dput(input)
structure(c(0, 0.5, 0.5, 1, 0.333333333333333, 0.333333333333333, 
0.333333333333333, 0, 0, 1, 0, 0.5, 0.5, 0, 0.333333333333333, 
0.333333333333333, 0.333333333333333, 0.5, 0.5, 0, 1, 0, 0, 0, 
0.333333333333333, 0.333333333333333, 0.333333333333333, 0.5, 
0.5, 0), .Dim = c(10L, 3L), .Dimnames = list(NULL, c("ranges_in_X51214", 
"ranges_in_X56499", "ranges_in_X6383")))

这是给定输入的预期输出:

> dput(output)
structure(list(X1 = c(1, 0.311278124459133, 0.311278124459133, 
0, 0.459147917027245, 0.459147917027245, 0.459147917027245, 1, 
1, 0), X2 = c(1, 0.311278124459133, 0.311278124459133, 1, 0.459147917027245, 
0.459147917027245, 0.459147917027245, 0.311278124459133, 0.311278124459133, 
1), X3 = c(0, 1, 1, 1, 0.459147917027245, 0.459147917027245, 
0.459147917027245, 0.311278124459133, 0.311278124459133, 1)), .Names = c("X1", 
"X2", "X3"), row.names = c(NA, 10L), class = "data.frame")

您的帮助将不胜感激。

【问题讨论】:

  • 在尝试并行化之前可以对 R 代码进行很多优化。
  • 你能添加所需的输出吗?
  • 我同意@F.Privé。过早的优化等等....en.wikiquote.org/wiki/Donald_Knuth
  • @ManishSaraswat 我已经更新了问题正文中的输出。

标签: r foreach


【解决方案1】:

这是删除内部循环的第一遍。
ifelse 语句的构造不正确。我也不明白 v2

input<-read.table(header=TRUE, text ="ranges_in_X51214 ranges_in_X56499 ranges_in_X6383
0.0              0.0               1
0.5              0.5               0
0.5              0.5               0")

output <- data.frame(matrix(NA, nrow = nrow(input), ncol = ncol(input)))

#a vector of same length as of each row in input dataframe
v2 <- numeric(length(input[1,]))
v2 <- 1
for (j in 1:nrow(input)){
  #take each row from input df
  v1 <- as.numeric(input[j,])
  # Take the sum of both vectors
  output_vec<-ifelse(v1 == 0,  1, sum(v1)+1)
  # write the output value at j row
  output[j,] <- output_vec
}

此输出与原始代码的输出相匹配。正如上面的 cmets 所说,可以进行额外的优化。

【讨论】:

  • 感谢您的回复。 V2和V1的目的是先生成2个向量。 V1 是循环的每次迭代中输入数据帧的第 j 行,V2 是另一个与 V1 长度相同的向量,只有 0 个值,但在第 i 个索引处我们将有 1。如果您理解我的解释,请更新您的相应地回答。谢谢!
  • 有一点要提一下,我实际上没有使用 sum 函数,我编写了一个自定义函数来计算 jansen-shanon-divergence,对于该计算,我们需要 2 个向量,该计算是为输入的第 j 个向量的每个索引完成(由内部 for 循环完成)。为了方便起见,我在这里使用了 sum 函数,这样我就不会通过添加其他外部函数来使帖子复杂化。
  • 上面的例子展示了如何向量化ifelse函数。抱歉,我无法对您的自定义构建函数进行矢量化。
  • 非常感谢您的努力。我已经用真实示例(包括我的自定义函数)和输入/输出示例更新了我的问题。如果现在对您有意义,请看一下。