【问题标题】:R - Naming multiple functions in a for loopR - 在 for 循环中命名多个函数
【发布时间】:2015-10-14 02:03:13
【问题描述】:

我有以下数据框:

> coc_comp_model[1:3,]
    Relationship Output  Input |r-Value|   Y-Intercept   Gradient
1   DG-r ~ DG-cl   DG-r  DG-cl 0.8271167  0.0027217513 12.9901380
2 CA3-r ~ CA3-cl  CA3-r CA3-cl 0.7461309  0.0350767684 27.6107963
3 CA2-r ~ CA2-cl  CA2-r CA2-cl 0.9732584 -0.0040992226 35.8299582

我想为数据框的每一行创建简单的函数。这是我尝试过的:

for(i in 1:nrow(coc_comp_model)) {
coc_glm_f[i] <- function(x)
x*coc_comp_model$Gradient[i] + coc_comp_model$Y-Intercept[i]
}

还尝试制作函数向量,这也不起作用。

感谢您阅读本文/帮助。

【问题讨论】:

    标签: r function for-loop assign


    【解决方案1】:

    类似这样的:

    myfunc<-function(datrow, x){
      x*as.numeric(datrow[6]) + as.numeric(datrow[5] )
    }
    

    然后您可以使用apply 在每一行上调用它,根据需要更改 x:

    apply(hzdata, 1, myfunc, x = 0.5)
    

    注意:使用dput() 共享您的数据比粘贴到子集中要容易得多。

    【讨论】:

      【解决方案2】:

      没有函数向量这样的东西。 R 中有 6 种原子向量类型:raw、logical、integer、double、complex 和 character,另外还有异构列表类型,最后还有鲜为人知的表达式类型,它基本上是解析树的向量(如当您调用 substitute() 函数时)。这些都是R中的向量类型。

      printAndType <- function(x) { print(x); typeof(x); };
      printAndType(as.raw(1:3));
      ## [1] 01 02 03
      ## [1] "raw"
      printAndType(c(T,F));
      ## [1]  TRUE FALSE
      ## [1] "logical"
      printAndType(1:3);
      ## [1] 1 2 3
      ## [1] "integer"
      printAndType(as.double(1:3));
      ## [1] 1 2 3
      ## [1] "double"
      printAndType(c(1i,2i,3i));
      ## [1] 0+1i 0+2i 0+3i
      ## [1] "complex"
      printAndType(letters[1:3]);
      ## [1] "a" "b" "c"
      ## [1] "character"
      printAndType(list(c(T,F),1:3,letters[1:3]));
      ## [[1]]
      ## [1]  TRUE FALSE
      ##
      ## [[2]]
      ## [1] 1 2 3
      ##
      ## [[3]]
      ## [1] "a" "b" "c"
      ##
      ## [1] "list"
      printAndType(expression(a+1,sum(1,2+3*4),if (T) 1 else 2));
      ## expression(a + 1, sum(1, 2 + 3 * 4), if (T) 1 else 2)
      ## [1] "expression"
      

      如果要在单个对象中存储多个函数,则必须使用列表,并且必须使用左值中的双括号索引运算符对其进行赋值:

      fl <- list();
      for (i in 1:3) fl[[i]] <- (function(i) { force(i); function(a) a+i; })(i);
      fl;
      ## [[1]]
      ## function (a)
      ## a + i
      ## <environment: 0x600da11a0>
      ##
      ## [[2]]
      ## function (a)
      ## a + i
      ## <environment: 0x600da1ab0>
      ##
      ## [[3]]
      ## function (a)
      ## a + i
      ## <environment: 0x600da23f8>
      sapply(fl,function(f) environment(f)$i);
      ## [1] 1 2 3
      sapply(fl,function(f) f(3));
      ## [1] 4 5 6
      

      在上面的代码中,我还演示了关闭循环变量的正确方法。这需要创建一个临时函数评估环境来保存i 的副本,然后返回的函数将围绕该评估环境关闭,以便它可以访问特定于迭代的i。这适用于支持动态函数和闭包的其他语言,例如 JavaScript。在 R 中,还有一个额外的要求是强制通过 force() 解决承诺,否则,对于每个独立生成的函数,承诺不会在第一次评估该特定生成函数之前得到解决,这将在那时锁定在该特定生成函数的承诺目标的当前值(在本例中为全局 i 变量)。还需要指出的是,这是一个极其浪费的设计,为每次迭代生成一个临时函数并对其进行评估,从而生成一个带有循环变量副本的新评估环境。

      如果您想使用这种设计,那么您的代码将变为:

      coc_glm_f <- list();
      for (i in 1:nrow(coc_comp_model)) {
          coc_glm_f[[i]] <- (function(i) { force(i); function(x) x*coc_comp_model$Gradient[i] + coc_comp_model$`Y-Intercept`[i]; })(i);
      };
      

      但是,为 data.frame 的每一行创建单独的函数可能没有意义。如果您希望 x 参数采用标量值(我的意思是单元素向量),那么您可以按如下方式定义函数:

      coc_glm_f <- function(x) x*coc_comp_model$Gradient + coc_comp_model$`Y-Intercept`;
      

      此函数是矢量化的,这意味着您可以为x 传递一个矢量,其中x 的每个元素将对应于coc_comp_model 的一行。例如:

      coc_comp_model <- data.frame(Relationship=c('DG-r ~ DG-cl','CA3-r ~ CA3-cl','CA2-r ~ CA2-cl'),Output=c('DG-r','CA3-r','CA2-r'),Input=c('DG-cl','CA3-cl','CA2-cl'),`|r-Value|`=c(0.8271167,0.7461309,0.9732584),`Y-Intercept`=c(0.0027217513,0.0350767684,-0.0040992226),Gradient=c(12.9901380,27.6107963,35.8299582),check.names=F);
      coc_glm_f(seq_len(nrow(coc_comp_model)));
      ## [1]  12.99286  55.25667 107.48578
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-09
        相关资源
        最近更新 更多