【问题标题】:Create multiple functions with changing names in a for loop in R在 R 的 for 循环中创建多个更改名称的函数
【发布时间】:2019-10-23 15:20:46
【问题描述】:

我有一个数据框“数据”,并且想要计算大约 30 个函数 f(CS)。目标是使用uniroot 为每个函数 f(CS) 找到 CS。我正在寻找一个循环,它生成函数 f(CS) 和函数的结果(即 CS)。

相关问题: R - Naming multiple functions in a for loopMultiple functions in for loop

函数应该有不同的名称(function_1、function_2、function_3 等),并且每个函数都使用数据框“data”中不同行的值。我尽力创建了一个最小可重现的例子:

data <- data.frame(A=c(154,154,154,154,110154,102500,0,0,0,0,205200,0,0,0,0), 
                   B=c(-0.647, -0.738, -0.749, -0.691, -0.600, 2.455, 2.358, 2.289, 2.264, 2.267, 2.455, 2.358, 2.289, 2.264, 2.267))

function_1 <- function(CS){
          sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5) - 100000)
      }

function_2 <- function(CS){
      sum(data$A[6:10]/(1+data$B[6:10]/100+CS/10000)^(1:5) - 100000)
  }

function_3 <- function(CS){
      sum(data$A[11:15]/(1+data$B[11:15]/100+CS/10000)^(1:5) - 200000)
  }

请注意,function_3 (200000) 中的常量不是错字。正如我所提到的,我用uniroot 计算根:

uniroot(function_1, c(-1000,1000))$root #267.3119
uniroot(function_2, c(-1000,1000))$root #4.500001
uniroot(function_3, c(-1000,1000))$root #14.5

我尝试使用如下两个 for 循环:

for (i in seq(from = 1, to = nrow(data)/5)){
noquote(paste0("function_",i,"")) <- function(CS){
           sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5))
   }
 }

for (i in seq(from = 1, to = nrow(data)/5)){
    uniroot(noquote(paste0("function_",i,")), c(-1000,1000))$root
  }

我不知道如何实现更改常量和更改函数名称,因为noquote(paste0()) 似乎不起作用。如果您需要任何进一步的信息,请告诉我。

【问题讨论】:

  • 使用get() 而不是noquote()。后者仅在打印时隐藏引号,它不会创建变量名。前者将返回给定 a 字符值及其名称的变量的值。但实际上最好将您的函数存储在一个命名列表中并完全避免get()。这是一种更像 R 的做事方式。

标签: r loops for-loop


【解决方案1】:

你已经接近了,但这并不是noquote 的用途。而是使用assignget 的组合,如下所示:

for (i in seq(from = 1, to = nrow(data)/5)){
   assign(paste0("function_",i)), function(CS){
           sum(data$A[1:5]/(1+data$B[1:5]/100+CS/10000)^(1:5))
   }
 }

for (i in seq(from = 1, to = nrow(data)/5)){
    uniroot(get(paste0("function_",i)), c(-1000,1000))$root
}

但是,我不确定您示例中的第一个循环是否真的重新创建了您在问题的第一个代码块中手动列出的所需函数。 data 的索引不应该也改变吗?像这样?

for (i in seq(from = 1, to = nrow(data)/5)){
   indices <- (1+(i-1)*5):(5+(i-1)*5)
   assign(paste0("function_",i,"")), function(CS){
           sum(data$A[indices ]/(1+data$B[indices]/100+CS/10000)^(1:5))
   }
 }

无论如何,我相信其他人会很快说您可能会找到一种方法来避免像这样遍历对象名称。大多数人会争辩说,最佳实践是手动分配功能,然后使其更加灵活。在您提供的示例中,您可以构造函数以将索引作为参数,然后您只需一个函数即可以多种方式使用:

flexibleFunction <- function(CS, indices){
      sum(data$A[indices]/(1+data$B[indices]/100+CS/10000)^(1:5) - 100000)
  }

uniroot(flexibleFunction , c(-1000,1000), 1:5)$root
uniroot(flexibleFunction , c(-1000,1000), 6:10)$root

【讨论】:

    猜你喜欢
    • 2015-10-14
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多