【问题标题】:speeding up for loops in R加速R中的循环
【发布时间】:2023-03-07 07:22:01
【问题描述】:

这不是要求新代码,而是更多关于 R 如何进行这样的计算。当然,我会采取任何和所有的建议来提高它的效率。

假设我有一个这样的脚本:

x=matrix(complex(1:10,1:10,imaginary = 1:10),ncol=2)
y=x+300
raw=list(x,y)
raw_complex = list(raw,raw,raw,raw)

这是一个复杂矩阵的列表。我正在尝试从中获取相位角:phase = atan(Im(x)/Re(x))

我当前的代码是:

for (m in 1:length(raw_complex)){
  for (n in 1:length(raw_complex[[m]])){
    for (i in 1:dim(raw_complex[[m]][[n]])[1]){
      for (j in 1:dim(raw_complex[[m]][[n]])[2]){
 raw_complex[[m]][[n]][i,j]=(atan(Im(raw_complex[[m]][[n]][i,j])/Re(raw_complex[[m]][[n]][i,j])))
      }}}}

我知道,我知道,避免 R 中的 for 循环。但从概念上讲,这让我更容易看到与 lapply 或 sapply 相比发生了什么。

我的问题是,在循环的每次迭代中,R 是否会在内存中复制整个列表或矩阵,而不是一次拉出每个单独的元素?显然我不希望 R 每次迭代都制作完整的副本。

我的真实数据集有一个 4 列表,列表的每个元素中有 95 个矩阵。每个矩阵都是 145x901,所以你可以看到我希望它尽可能快。

哦,如果输出是实数而不是复数,那就太好了。我尝试在atan() 前面添加as.numeric(),但这似乎没有帮助。

谢谢!

【问题讨论】:

  • 输出很复杂。不科学但虚部为0

标签: r loops memory-management


【解决方案1】:

利用 R 是矢量化的事实。具体来说,这意味着您可以直接在向量或矩阵上应用许多计算。

例如,为相位定义一个函数:

phase <- function(x)atan(Im(x)/Re(x))
phase(x)

使用这个简单的函数,您可以计算矩阵中每个单元格的相位:

          [,1]      [,2]
[1,] 0.7853982 0.7853982
[2,] 0.7853982 0.7853982
[3,] 0.7853982 0.7853982
[4,] 0.7853982 0.7853982
[5,] 0.7853982 0.7853982

现在您离在您的列表中应用此phase 函数仅一步之遥。为此,您可以使用lapply()

lapply(raw, phase)
[[1]]
          [,1]      [,2]
[1,] 0.7853982 0.7853982
[2,] 0.7853982 0.7853982
[3,] 0.7853982 0.7853982
[4,] 0.7853982 0.7853982
[5,] 0.7853982 0.7853982

[[2]]
            [,1]       [,2]
[1,] 0.003322247 0.01960533
[2,] 0.006622420 0.02279735
[3,] 0.009900667 0.02596819
[4,] 0.013157135 0.02911798
[5,] 0.016391974 0.03224688

但您真正追求的是将此函数递归地应用于您的列表列表。为此,存在函数rapply() - 其中r 代表递归:

z <- rapply(raw_complex, phase, how = "list")
str(z)
List of 4
 $ :List of 2
  ..$ : num [1:5, 1:2] 0.785 0.785 0.785 0.785 0.785 ...
  ..$ : num [1:5, 1:2] 0.00332 0.00662 0.0099 0.01316 0.01639 ...
 $ :List of 2
  ..$ : num [1:5, 1:2] 0.785 0.785 0.785 0.785 0.785 ...
  ..$ : num [1:5, 1:2] 0.00332 0.00662 0.0099 0.01316 0.01639 ...
 $ :List of 2
  ..$ : num [1:5, 1:2] 0.785 0.785 0.785 0.785 0.785 ...
  ..$ : num [1:5, 1:2] 0.00332 0.00662 0.0099 0.01316 0.01639 ...
 $ :List of 2
  ..$ : num [1:5, 1:2] 0.785 0.785 0.785 0.785 0.785 ...
  ..$ : num [1:5, 1:2] 0.00332 0.00662 0.0099 0.01316 0.01639 ...

这会很快——不是因为你避免了循环——而是因为你在矩阵上计算,而不是每个单元格。

更重要的是,它简洁易读。

【讨论】:

  • 当然,如果这些矩阵的维度都相同,那么数组将是比嵌套列表更好的数据结构。
  • R 中已经有一个Arg 函数可以完成phase 的工作。
  • Roland,你是说3D阵列吗?那有什么作用呢?
猜你喜欢
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多