【问题标题】:How to convert for loop to apply in r [closed]如何将 for 循环转换为适用于 r [关闭]
【发布时间】:2019-08-21 12:58:13
【问题描述】:

我有以下循环。我正在尝试将其转换为使用apply 函数而不是循环,但我不知道如何重写代码。

for (i in 1:dim(Y)[2]) {
     K = K_origin
     print(i)

     e = lmmlite::eigen_rotation(K, t(Y)[i,], use_cpp = T)
     VC = lmmlite::fitLMM(
       e$Kva,
       e$y,
       e$X,
       reml = T,
       use_cpp = T,
       tol = 1e-6,
       check_boundary = T
     )

     write.table(
       VC$sigmasq_g,
       "Vg_temp.txt",
       row.names = F,
       col.names = F,
       append = T,
       quote = F,
       sep = "\n"
     )
     write.table(
       VC$sigmasq_e,
       "Ve_temp.txt",
       row.names = F,
       col.names = F,
       append = T,
       quote = F,
       sep = "\n"
     )
}

我想要这样的结果

Vg                  Ve
1.15521325512487    0.755118863386436
0.579039221720728   1.21733212837417
0.372439354137817   0.296327744338075
0.0668396114713355  0.300417453013007
0.00771158861391208 0.100176380868691
0.210174870097273   0.141907482831872

【问题讨论】:

    标签: r for-loop apply


    【解决方案1】:

    R 的 apply 函数必须表述为 1) 要迭代的东西,以及 2) 应用于 (1) 中每个元素的函数。

    但是!您是否会从将特定循环转换为应用程序中获得任何好处,这是值得怀疑的。如果您的循环很慢,我猜这是由于执行的操作,而不是“R 在循环上很慢”。如果Y 中只有 6 行,则将循环重新表述为 apply 将一无所获!

    对于您的循环,每个i 都是独立的(与循环i 不同,当结果取决于i-1 的计算时)。所以这使得重新制定非常容易。一般来说,

    for (i in some_sequence) {
      do something with i
    }
    

    可以改写为

    my_do_something <- function(i) {
      do something
    }
    
    for (i in some_sequence) {
      my_do_something(i)
    }
    

    可以再次直接改写为

    sapply(some_sequence, my_do_something)
    

    在你的情况下,这将是

    my_rotate <- function(i) {
      e = lmmlite::eigen_rotation(K, t(Y)[i,], use_cpp = T)
      VC = lmmlite::fitLMM( ... )
      write.table(...)
      write.table(...)
      NULL
    }
    
    sapply(seq_len(dim(Y)[2]), my_rotate)
    

    注意我是如何在函数底部添加NULL 的?那是因为apply 将收集迭代函数的返回值; write.table 返回不可见的写入数据。试试没有最后一个NULL 的函数,看看apply 返回什么。

    但是等等,还有更多!

    由于您正在迭代特定的行(特别是询问apply),所以我们只需删除i 的内容并将该行提供给函数:

    my_rotate_row <- function(x) {
      # you might or might not need to either use x as is, transpose it as t(x) or double transpose it, t(t(x)), to get the correct orientation. 
      # x is most likely an atomic vector, whereas `eigen_rotation` might be requiring either a row-vector or a column vector.
    
      e = lmmlite::eigen_rotation(K, x, use_cpp = T)
      VC = lmmlite::fitLMM( ... )
      # lets collect data directly into a data.frame or matrix, instead of using files:
      c(VC$sigmasq_g, VC$sigmasq_e)
    }
    

    现在你可以使用apply:

    apply(Y, 2, my_rotate_row)
    

    【讨论】:

      猜你喜欢
      • 2016-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-03
      • 2021-12-16
      • 2018-05-10
      • 1970-01-01
      相关资源
      最近更新 更多