【问题标题】:What is the practical use of the identity function in R?R中恒等函数的实际用途是什么?
【发布时间】:2011-10-29 20:17:46
【问题描述】:

Base R 定义了一个identity 函数,一个返回其参数的普通恒等函数(引用自?identity)。

定义为:

identity <- function (x){x}

为什么这样一个微不足道的函数会有用?为什么它会包含在基础 R 中?

【问题讨论】:

  • 我已经看到它在curve(identity(x)) 的上下文中使用(而不是稍微(?)更不透明的curve(x*1)curve(x+0) ...
  • @BenBolker 为什么不简单地curve(x)
  • 试试看——它不起作用 (Error in eval(expr, envir, enclos) : could not find function "x") 因为curve 使用了有趣的评估规则...
  • 前几个答案暗示了函数式编程。关于 R 和函数式编程的一些有用问题:stackoverflow.com/q/4874867/602276stackoverflow.com/q/6167791/602276stackoverflow.com/q/2228544/602276

标签: r functional-programming identity


【解决方案1】:

由于这个问题已经被浏览了 8k 次,所以即使在它写完 9 年后也可能值得更新。

在一篇名为“调试管道的简单技巧(在 magrittr、base R 或 ggplot2 内)”的博文中,作者指出了 identity() 在不同类型管道的末端如何非常有用。可以在此处找到带有示例的博文:https://rstats-tips.net/2021/06/06/simple-tricks-for-debugging-pipes-within-magrittr-base-r-or-ggplot2/

如果管道链是以某种方式编写的,即每个“管道”符号都位于行尾,您可以通过注释掉任何行来排除执行。除了最后一行。如果您将identity() 添加为最后一行,则无需将其注释掉。因此,您可以通过将其注释掉来暂时排除任何更改数据的行。

【讨论】:

    【解决方案2】:

    我只是这样使用它:

    fit_model <- function(lots, of, parameters, error_silently = TRUE) {
    
      purrr::compose(ifelse(test = error_silently, yes = tryNA, no = identity),
                     fit_model_)(lots, of, parameters)
    }
    
    tryNA <- function(expr) {
      suppressWarnings(tryCatch(expr = expr,
                                error = function(e) NA,
                                finally = NA))
    }
    

    【讨论】:

      【解决方案3】:

      这是用法示例:

          Map<Integer, Long> m = Stream.of(1, 1, 2, 2, 3, 3)
                  .collect(Collectors.groupingBy(Function.identity(),
                          Collectors.counting()));
          System.out.println(m);
          output:
          {1=2, 2=2, 3=2}
      

      这里我们将 int 分组到一个 int/count 映射中。 Collectors.groupingBy 接受一个函数。在我们的例子中,我们需要一个返回参数的函数。请注意,我们可以改用e-&gt;e lambda

      【讨论】:

        【解决方案4】:

        远离函数式编程,identity 还用于 R 中的另一个上下文,即统计。这里用来指代generalized linear models中的身份link function。有关这方面的更多详细信息,请参阅 ?family?glm。这是一个例子:

        > x <- rnorm(100)
        > y <- rpois(100, exp(1+x))
        > glm(y ~x, family=quasi(link=identity))
        
        Call:  glm(formula = y ~ x, family = quasi(link = identity))
        
        Coefficients:
        (Intercept)            x
              4.835        5.842
        
        Degrees of Freedom: 99 Total (i.e. Null);  98 Residual
        Null Deviance:      6713
        Residual Deviance: 2993         AIC: NA
        

        但是,在这种情况下,将其解析为字符串而不是函数将实现相同的效果:glm(y ~x, family=quasi(link="identity"))

        编辑:如下面的 cmets 所述,base::identity 函数不是链接构造函数使用的,它仅用于解析链接名称。 (而不是删除这个答案,我会留下它来帮助澄清两者之间的区别。)

        【讨论】:

        • 这在一个(现已删除的)答案中提到...identity 在这种情况下显然实际上并不是指base::identity。见make.link中的代码;它只是匹配名称“身份”。
        • @nullglob :确实。答案是我的,我删除了它,因为它不正确。 glm 的系列构造函数不使用标识函数,它们评估一个字符串(即使您可以传递不带引号的参数)。
        【解决方案5】:

        出现在简单的code base search 上的一个用途是为tryCatch 中最基本类型的错误处理函数提供便利。

        tryCatch(...,error = identity)
        

        相同(哈哈!)
        tryCatch(...,error = function(e) e)
        

        所以这个处理程序会捕获一条错误消息,然后简单地返回它。

        【讨论】:

        • 在这对我有意义之前,我必须做更多的思考。我一直避免了解trytryCatch 的工作原理。感谢您的示例和参考。
        【解决方案6】:

        不了解 R,但在函数式语言中,人们经常将函数作为参数传递给其他函数。在这种情况下,常量函数(对任何参数都返回相同的值)和恒等函数在乘法中的作用类似于 0 和 1。

        【讨论】:

        • 你能再解释一下吗?我了解能够将函数作为参数传递的一点。但是扮演0和1的角色是什么意思?
        • 而R是一种相对函数式的语言。至少,它具有一流的函数、闭包、专注于不可变数据结构、映射和过滤器、匿名函数等。所以,是的,这可能就是包含 identity 的原因。
        • 在 R 中将函数作为参数的函数的一个很好的例子是 apply 函数族:ats.ucla.edu/stat/r/library/advanced_function_r.htm#apply。这些函数对于处理数据集非常强大。
        • 这种东西的实际用途可以是,例如,作为“转换”类型的参数的默认值。这类似于具有“乘法因子”类型的参数并将其默认值设置为 1.0。在这两种情况下,默认值都具有无操作的效果。不必显式指定(例如通过设置 boolean do_not_transform),而是隐式指定它是有用的,只需作为参数的属性(即,它充当身份运算符)。
        • @Andrie - 我可以在 Haskell 中举个例子。假设我有一个 Maybe Int 类型的值,我对这个数字感兴趣。有一个函数可能是 d f x = case x of { Nothing -> d;只是 i -> f i } 我可以用来提取它。它给了我将函数应用于有效负载的结果,或者如果 x 为 Nothing,则为默认值。因此,如果我希望值不变,我只需传递 id (这是 haskell 中标识函数的名称)。我知道这对于那些从不觉得有必要的人来说听起来是人为的,但是,也许你只是编程的“功能性”还不够。
        【解决方案7】:

        我不时使用它与命令的应用功能。

        例如,您可以将t() 写为:

        dat <- data.frame(x=runif(10),y=runif(10))
        apply(dat,1,identity)
        
               [,1]      [,2]      [,3]      [,4]      [,5]      [,6]       [,7]
        x 0.1048485 0.7213284 0.9033974 0.4699182 0.4416660 0.1052732 0.06000952
        y 0.7225307 0.2683224 0.7292261 0.5131646 0.4514837 0.3788556 0.46668331
               [,8]      [,9]      [,10]
        x 0.2457748 0.3833299 0.86113771
        y 0.9643703 0.3890342 0.01700427
        

        【讨论】:

        • +1 换句话说,identity 被用作no-operation 开关,以真正利用被调用函数的转换特性。不错。
        • @Andrie 没错。并且说得比我想象的更优雅:-)
        • 不是我,老大。我是从@tripleee 删除的答案中转述的,实际上我发现这对于为其他答案提供上下文非常有用。
        【解决方案8】:

        不管它值多少钱,它位于基础包源代码中的funprog.R(函数式编程的东西),并在 2008 年作为“便利函数”添加:我可以想象(但不能举一个直接的例子!)在函数式编程方法中会有一些上下文(即使用FilterReduceMap 等),其中有一个身份函数会很方便......

        r45063 | hornik | 2008-04-03 12:40:59 -0400 (Thu, 03 Apr 2008) | 2 lines
        
        Add higher-order functions Find() and Position(), and convenience
        function identity().
        

        【讨论】:

        • 也和force一样
        猜你喜欢
        • 2011-03-14
        • 1970-01-01
        • 2011-04-02
        • 2019-05-17
        • 2015-04-22
        • 2021-07-22
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        相关资源
        最近更新 更多