【问题标题】:R: Storing outputs from a function containing a loop (or removing the loop)R:存储包含循环的函数的输出(或删除循环)
【发布时间】:2021-03-20 14:52:15
【问题描述】:

编辑:现在解决了,下面的解决方案。

我得到了一个 R 函数,我需要为不同的输入运行多次,并提取输出(稍后将进入数据帧)。下面的可重现示例。

这两个问题是:

  1. 我不知道如何将数据从下面的函数输出到可以读取的东西,如矩阵、字符串、其他对象等。我读过关于将东西输出到列表的内容,但是(以及由于无法捕获对象中的输出)这似乎与第二个问题相冲突,即:
  2. 该函数包含一个循环,因此当我尝试输出数字时,我通常只从循环的第一次迭代中获得输出,当我需要所有输出时(大多数时候只有两个一组数字,但有时还有更多)。

有没有人能请教如何重做这个函数,以便它输出一个我可以从中读取值的对象?也许循环可以用 map/lapply 函数或类似函数替换,但我真的很难在编写这些代码时绞尽脑汁。

可重现的示例(注意,需要 cmprsk 和生存包):

numbercruncher<-function(y,ev)
{
  est<-round(y$est*100,1)
  low<-round((exp(log(y$est)-1.96*sqrt(y$var)/y$est))*100,1)
  up<-round((exp(log(y$est)+1.96*sqrt(y$var)/y$est))*100,1)
  d<-nrow(est)/2
  for (i in 1:d){
    rws<-i+d*(ev-1)
    cat("group",i,fill=TRUE)
    out<-t(rbind(est[rws,],low[rws,],up[rws,]))
    colnames(out)<-c("value1","value2","value3")
    print(out)
  }
}

set.seed(1234)
v <-sample(0:2, 1500, replace = TRUE)
t <-sample(0:90, 1500, replace = TRUE)
g <- sample(0:4, 1500, replace = TRUE)

incidence.model <- cuminc(t, v, g, cencode = 0)

incidence.y<-timepoints(incidence.model,times=c(90))

numbercruncher(incidence.y,1)

输出:

     value1 value2 value3
[1,]   48.3   41.7     56
group 2
     value1 value2 value3
[1,]   46.9     40     55
group 3
     value1 value2 value3
[1,]   50.1   42.1   59.6
group 4
     value1 value2 value3
[1,]   49.7   41.2     60
group 5
     value1 value2 value3
[1,]   43.6   37.3   50.9

在此示例中,理想情况下,我会得到一个包含所有 value1 的向量,另一个包含所有 value2 和一个包含所有 value3 的向量。

感谢您的宝贵时间和帮助!

使用'解决了

numbercruncher<-function(y,ev)
{
  out.final <<- numeric()
  est<-round(y$est*100,1)
  low<-round((exp(log(y$est)-1.96*sqrt(y$var)/y$est))*100,1)
  up<-round((exp(log(y$est)+1.96*sqrt(y$var)/y$est))*100,1)
  d<-nrow(est)/2
  for (i in 1:d){
    rws<-i+d*(ev-1)
    cat("group",i,fill=TRUE)
    out<-t(rbind(est[rws,],low[rws,],up[rws,]))
    colnames(out)<-c("value1","value2","value3")
    print(out)
    out.final <<- append(out.final, out)
  }
}

set.seed(1234)
v <-sample(0:2, 1500, replace = TRUE)
t <-sample(0:90, 1500, replace = TRUE)
g <- sample(0:4, 1500, replace = TRUE)

incidence.model <- cuminc(t, v, g, cencode = 0)

incidence.y<-timepoints(incidence.model,times=c(90))

numbercruncher(incidence.y,1)

这给出了一个数字向量,可以使用以下方法将其转换为矩阵:

out.final.matrix <- matrix(out.final, ncol = 3, byrow = TRUE)

【问题讨论】:

  • 请注意,您可以在下面回答您自己的问题。

标签: r function loops extract purrr


【解决方案1】:

根据您解决的解决方案,建议在 R 中避免使用范围赋值运算符 &lt;&lt;-,由于调试和副作用原因,这可能难以维护代码。此外,避免使用append 在循环内增长对象。

考虑改为为简化向量(因为所有元素都是数字)调用类似 sapplyvapply 的应用函数来收集返回的元素。您也许可以取消 rbindt 电话。 (请注意以下内容未经测试。)

numbercruncher <- function(y, ev)
{
  est <- round(y$est * 100, 1)
  low <- round((exp(log(y$est) - 1.96 * sqrt(y$var) / y$est)) * 100, 1)
  up <- round((exp(log(y$est) + 1.96 * sqrt(y$var) / y$est)) * 100, 1)
  d <- nrow(est) / 2

  results <- sapply(1:d, function(i) {
    rws <- i+d*(ev-1)
    cat("group",i,fill=TRUE)

    # RETURN NAMED VECTOR
    out <- c(value1=est[rws,], value2=low[rws,], value3=up[rws,])
    return(out)  # REDUNDANT LINE BUT ILLUSTRATIVE
  })

  return(results)  # REDUNDANT LINE BUT ILLUSTRATIVE
}

out.final2 <- numbercruncher(incidence.y,1)

尝试将sapply 换成vapply 以获得更快的回报(同样,未经测试):

results <- vapply(1:d, function(i) {
    rws <- i+d*(ev-1)
    cat("group",i,fill=TRUE)

    # RETURN NAMED VECTOR
    out <- c(value1=est[rws,], value2=low[rws,], value3=up[rws,])
    return(out)

}, numeric(3))

上面的输出与 OP 的内容相同。上面的结果不是 15 的向量,而是一个 3 X 5 的矩阵,可以很容易地转换为向量。

out.final
#  [1] 48.3 41.7 56.0 46.9 40.0 55.0 50.1 42.1 59.6 49.7 41.2 60.0 43.6 37.3 50.9

out.final2
#        [,1] [,2] [,3] [,4] [,5]
# value1 48.3 46.9 50.1 49.7 43.6
# value2 41.7 40.0 42.1 41.2 37.3
# value3 56.0 55.0 59.6 60.0 50.9

identical(out.final, as.vector(out.final2))
# [1] TRUE

【讨论】:

  • 谢谢芭菲!这消除了循环,但不幸的是并没有解决我正在使用范围分配的输出问题。我在其他地方看到了关于该分配和附加命令的类似警告,所以我知道它们并不理想,并将努力学习 R 的做事方式!
  • 结果是一样的,只是形式不同而已。请参阅最后带有演示的编辑,其中结果与您的out.final 相同。在我的解决方案中,您必须将 &lt;- 分配给调整函数的对象:out.final2 &lt;- numbercruncher(incidence.y,1)。由于没有使用范围,因此没有像您的解决方案那样从函数内部更新全局对象的副作用。
【解决方案2】:

使用范围分配找到的非理想解决方案并与原始问题一起发布 - 尽管我知道这不是最好的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2018-10-20
    • 2016-03-02
    • 1970-01-01
    • 2023-01-28
    • 2023-03-08
    相关资源
    最近更新 更多