高阶函数查找列表的最小值

Higher order function find min of list

我正在循环估计并保存所有估计对象,然后选择偏差最小的对象。为此,我想使用 Filter/Map/Position 函数,但找不到解决方案,因为它总是 returns 列表的第一个对象,而不是第二个。我可能对 Position 函数的工作原理有一些误解,但想知道我错过了什么。

MWE:

ls<-list(3,2,4)
Position(min,Map(function(x) {x^2}, ls))

我最终使用了 unlist 和 which.min

您最终执行了正确的程序。为什么?首先,我们将从帮助页面中提取一个重要的摘录:

Position(f, x, right = FALSE, nomatch = NA_integer_)

Find and Position are patterned after Common Lisp's find-if and position-if, respectively. If there is an element for which the predicate function gives true, then the first or last such element or its position is returned depending on whether right is false (default) or true, respectively. If there is no such element, the value specified by nomatch is returned. The current implementation is not optimized for performance.

因此,Position() 将对 x 的所有元素应用 f(),并且当 f() 的结果为 TRUE(直接或通过强制转换) Position() 将 return 该元素的索引(如果没有最终成为 TRUE 那么它 return 是分配给 nomatch 的值)。

这是实际的 Position() 函数源代码:

Position <- function (f, x, right=FALSE, nomatch=NA_integer_) {

  ind <- seq_along(x)
  if (right) ind <- rev(ind)

  for (i in ind) {
    if (f(x[[i]])) return(i)
  }

  nomatch

}

按照源代码,您可以 prbly 看到 min() 在列表的第一个元素上被调用,它 return 是列表中向量的 min() 的值位置 1 并且该值不为零,因此它认为它做得很好并且 returns 它所在的列表索引。

如果你一直在做:

Position(min, Map(function(x) {x-3}, dat))

那么你会看到结果是:

## [1] 2

并且可能认为它在工作,但它只是 returning 因为 33-3 == 00 列表的第一个元素被强制转换至 FALSE.

注意:ls 也是基函数的名称,这很好,因为 R 知道根据使用上下文做什么,但我不喜欢在函数调用过程中可能导致奇怪的错误粉碎非常常见的核心命名空间元素所以我使用 dat 而不是 ls.

Position() 背后的想法更像是:

eqls4 <- function(x) x==4

Position(eqls4, Map(function(x) {x^2}, dat))

哪个 return:

## [1] 2

所以,你最终做的是 100% 正确的。

另请注意,purrr 包提供了替代功能习语,(IMO)往往更具可读性 + 有确保正确类型得到维护的方法,并且它导出 %>% 因此管道也很容易可用:

library(purrr)

map(dat, ~.^2) %>% 
  flatten_dbl() %>% 
  which.min()